How to check the multiple values against a same name attribute in xml column of DB2 using XMLQuery? - db2

Here is my query which I'm using to fetch the data from my table.
SELECT XMLQUERY('$INFO/root/database_systems/system/#name = ("SYS1","SYS2","SYS3")')
FROM MyTable WHERE ACCT_ID = 'ID-1234';
Ok actually it is returning me true. Just because of the first value SYS1. It exists in the hierarchy but not the others. I just want to compare multiple values.
Please suggest a way to achieve this functionality. Thanks
<root>
<database_systems>
<system name="SYS1">1</system>
</database_systems>
</root>

If I understand correctly, you want to check for a database_systems element that contains at least all of the child elements:
<system name="SYS1">...</system>
<system name="SYS2">...</system>
<system name="SYS3">...</system>
If that is correct then you need to AND your conditions together, what you had previously was an OR:
SELECT XMLQUERY('not(empty($INFO/root/database_systems[system/#name eq "SYS1"][system/#name eq "SYS2"][system/#name eq "SYS3"]))')
FROM MyTable WHERE ACCT_ID = 'ID-1234';
I have used three predicates to achieve the AND, and then I check that a match was found using not(empty(...)). There are plenty of other ways to achieve this too.

Related

Is there a way to combine the data of two rows with some intersecting data in postgreSQL?

Good morning! I am currently working on creating a postgreSQL database with some client information, however I ran into an issue which I wasn't able to solve with my basic knowledge of SQL. Searching for this method also returned with no results which I found useful or applicable.
I have two tables: 'mskMobile' and 'emailData'. Both of those tables contain a column named 'email' and some of those emails overlap. I figured out that I can view those intersecting emails by requesting
SELECT "mailData".email
FROM "mailData"
JOIN "mskMobile"
ON "mailData".email="mskMobile".email;
Now I want to write the data of two other columns of those common rows in 'mskMobile' named 'name' and 'surname' to the corresponding columns in 'emailData' (named identically), however I cannot find any answer on how to do so. Any suggestions on how to execute this action?
UPDATE "mksMobile" SET name = "mailData".name, surname = "mailData".surname
FROM "mailData"
WHERE "mailData".email = "mskMobile".email;
After a bit more research I came up with a following way of declaring it:
SELECT "mailData".email, "mskMobile".num, "mskMobile".name
FROM "mailData"
INNER JOIN "mskMobile"
ON "mailData".email="mskMobile".email;
This allowed me to build a new table with the data combined.

Get the index number of a column name with Perl DBI

Given this perl DBI query:
$qh = $db_connection->prepare ('SELECT addresses.* from addresses WHERE 1');
The addresses table structure might change in the future, that is, some new columns may get inserted into it. So there's no guarantee which index number a particular column may get assigned to.
When I do a $qh->fetchrow_array, I want to be able to determine what the index number of a particular column is so I can check to see if it's empty. For example, I want to see if the mail_addr column is empty like so:
if (!$$row[$index_number]) {
do_something();
}
How can I determine what the value $index_number should be?
This can be determined via $sth->{NAME}. However, this situation is probably more appropriate for fetchrow_hashref which implements all the gluing of indices to field names you're looking for:
while ( my $row = $qh->fetchrow_hashref ) {
if (!$row->{mail_addr}) {
do_something();
}
}
Also consider the FetchHashKeyName attribute, fetchrow_hashref('NAME_lc'), or the $sth->{NAME_lc} attribute, which will guarantee the case of fieldnames presented by the DBI. Different SQL engines will normalize the identifier case differently, often depending on whether the identifier was quoted when declared.
Firstly, please don't use the $$row[$index_number] syntax. Anyone looking at your code will be expecting to see that written as $row->[$index_number].
You've worked out why SELECT * is a bad idea. So don't do that. List the specific columns that you are interested in - that way you can impose your own order (fetchrow_array returns columns in the order that they appear in the SELECT clause).
Alternatively, switch to one of the hash-based fetch methods like fetchrow_hashref.
But the best alternative would be to look at using DBIx::Class.

Rails PG GroupingError column must appear in the GROUP BY clause

there are a few topics about this already with accepted answers but I couldn't figure out a solution based on those:
Eg:
Ruby on Rails: must appear in the GROUP BY clause or be used in an aggregate function
GroupingError: ERROR: column must appear in the GROUP BY clause or be used in an aggregate function
PGError: ERROR: column "p.name" must appear in the GROUP BY clause or be used in an aggregate function
My query is:
Idea.unscoped.joins('inner join likes on ideas.id = likes.likeable_id').
select('likes.id, COUNT(*) AS like_count, ideas.id, ideas.title, ideas.intro, likeable_id').
group('likeable_id').
order('like_count DESC')
This is fine in development with sqlite but breaks on heroku with PostgreSQL.
The error is:
PG::GroupingError: ERROR: column "likes.id" must appear in the GROUP BY clause or be used in an aggregate function
If I put likes.id in my group by then the results make no sense. Tried to put group before select but doesn't help. I even tried to take the query into two parts. No joy. :(
Any suggestions appreciated. TIA!
I don't know why you want to select likes.id in the first place. I see that you basically want the like_count for each Idea; I don't see the point in selecting likes.id. Also, when you already have the ideas.id, I don't see why you would want to get the value of likes.likeable_id since they'll both be equal. :/
Anyway, the problem is since you're grouping by likeable_id (basically ideas.id), you can't "select" likes.id since they would be "lost" by the grouping.
I suppose SQLite is lax about this. I imagine it wouldn't group things properly.
ANYWAY(2) =>
Let me propose a cleaner solution.
# model
class Idea < ActiveRecord::Base
# to save you the effort of specifying the join-conditions
has_many :likes, foreign_key: :likeable_id
end
# in your code elsewhere
ideas = \
Idea.
joins(:likes).
group("ideas.id").
select("COUNT(likes.id) AS like_count, ideas.id, ideas.title, ideas.intro").
order("like_count DESC")
If you still want to get the IDs of likes for each item, then after the above, here's what you could do:
grouped_like_ids = \
Like.
select(:id, :likeable_id).
each_with_object({}) do |like, hash|
(hash[like.likeable_id] ||= []) << like.id
end
ideas.each do |idea|
# selected previously:
idea.like_count
idea.id
idea.title
idea.intro
# from the hash
like_ids = grouped_like_ids[idea.id] || []
end
Other readers: I'd be very interested in a "clean" one-query non-sub-query solution. Let me know in the comments if you leave a response. Thanks.

left join in zend framework

I am new in ZF and i would like to left join a table named country on country.id=firm_dtl.firm_country
$firmobj->fetchAll($firmobj->select($this)->where("firm_name like '$alpha%'")->order('firm_name'));
How can i do this.
I am trying with this code :-
$firmobj->select($this)->joinLeft(array("c"=>"country"), "c.id = firm_dtl.firm_country","c.name")->where("firm_name like '$alpha%'")->order('firm_name');
Here are some things that you can try to get the left join working and also to improve security.
I usually build my select statements across many lines and so I like to put it in a variable. To debug, I simply comment out the lines that I don't need.
$select = $firmobj->select()->from('country');
You'll want to setIntegrityCheck(false) because you probably won't be changing and committing the results from the query. Here's a quote from the ZF documentation about it.
The Zend_Db_Table_Select is primarily used to constrain and validate
so that it may enforce the criteria for a legal SELECT query. However
there may be certain cases where you require the flexibility of the
Zend_Db_Table_Row component and do not require a writable or deletable
row. for this specific user case, it is possible to retrieve a row or
rowset by passing a FALSE value to setIntegrityCheck().
$select->setIntegrityCheck(false);
Here is where you join. You can replace field1, field2, fieldn with the fields in the firm_dtl table that you want to see in the results.
$select->joinLeft(array('c' => 'country'), 'c.id = firm_dtl.firm_country', array('field1', 'field2', 'fieldn'));
Use parameter substitution to avoid SQL injection attacks.
$select->where('firm_name LIKE ?', "$alpha%");
And finally order the results and fetch the row set.
$select->order('firm_name');
$rowSet = $firmobj->fetchAll($select);
The 3rd parameter of joinLeft function should be an array of columns you want to fetch.
$firmobj->select($this)
->joinLeft(array("c"=>"country"), "c.id = firm_dtl.firm_country", array("c.name"))
->where("firm_name like '$alpha%'")
->order('firm_name');
Additionally, the better way is to use where function this way:
->where("firm_name like ?", $alpha . "%")
This way is the safer solution.

Filtering with P6SPY

Is there a way to set the filter in p6spy, such that it only logs "insert/delete/update" and NOT "select" SQL statements?
Documentation of p6spy mentions:
"P6Spy allows you to monitor specific tables or specific statement types"
An example they gave was the following:
An example showing capture of all
select statements, except the orders
table follows:
filter = true
# comma separated list of tables to include
include = select
# comma separated list of tables to exclude
exclude = orders
So I thought, there must be a way to include insert, delete, updates and exclude select... hence, I prepared my properties file like so:
filter = true
# comma separated list of tables to include
include = insert,update,delete
# comma separated list of tables to exclude
exclude = select
but that does not seem to work. Anyone with any suggestions??
The key to the answer is in the comments
# comma separated list of tables to include
include = select
select is a name of a table, not the type of a statement.
It seems impossible to filter by statement types (at least by select/update/delete) easily. You'll be able to do it by using
# sql expression to evaluate if using regex filtering
sqlexpression=
#allows you to use a regex engine or your own matching engine to determine
#which statements to log
stringmatcher=com.p6spy.engine.common.GnuRegexMatcher
The definition has changed. In short, you can use what the OP used i.e:
filter=true
# comma separated list of *******STRINGS******* to include
include=insert,update,delete
# comma separated list of *******STRINGS******* to exclude
exclude=select
Or if you want to have more control, you can use sqlexpression like so:
filter=true
sqlexpression=^(.*(from\\scustomers).*)$