I have the table structure as follows
ID DefID AttrID ValInt ValReal ValDate ValStr
1 1 1 NULL NULL NULL hi
2 1 1 NULL NULL NULL hi
3 1 1 NULL NULL NULL hi
4 1 1 NULL NULL NULL hi
1 1 1 0 NULL NULL NULL
2 1 1 1 NULL NULL NULL
3 1 1 0 NULL NULL NULL
4 1 1 0 NULL NULL NULL
This is my table named Table, Now I want to get the ID by query only having ValStr='h1' and ValInt=1, meaning only those ID whose ValStr is hi and also ValInt = 1 belonging to the same ID column. Please help.
Here what I have did till Now.
select ID from Table where DefID=1 and ValStr='hi' and ValInt=1
My Actual answer should be
ID
2
but I am getting this from the above query
ID
1
2
3
4
One more option
select t1.ID from Table t1
where EXISTS (
SELECT *
FROM Table t2
WHERE t2.DefID = 1 AND t2.ValStr = 'hi'
) and t1.ValInt = 1
SELECT ID
FROM TableName
WHERE (DefID = 1 AND ValInt = 1) OR
(DefID = 1 AND ValStr = 'hi')
GROUP BY ID
HAVING COUNT(*) = 2
SQLFiddle Demo
How about
SELECT distinct t1.ID
FROM Table t1
JOIN Table t2 on t1.id = t2.id
WHERE t1.DefID=1 and t2.DefID = 1
AND t1.ValStr='hi' and t2.ValInt=1
or (depending on taste)
SELECT distinct t1.ID
FROM Table t1
JOIN Table t2 on t1.id = t2.id AND t1.DefID=1 = t2.DefID
WHERE t1.DefID=1 AND t1.ValStr='hi' and t2.ValInt=1
Related
I have a pretty complex query I need to do which requires data from 6 different tables. The tables look like this:
Table 1
id
name
1
first_row
Table 2
id
table1_id
count
1
1
3
2
1
5
3
1
8
Table 3
id
table1_id
1
1
2
1
Table 4
id
table3_id
count
1
1
2
2
2
4
Table 5
id
table4_id
count
Table 6
id
table5_id
count
status
And I basically want to collect the count and sums from each of the table into 1 row such as:
Result
table1_id
table1_name
SUM(table2_count)
SUM(table4_count)
SUM(table5_count)
SUM(case when table6.status = 3 THEN 1 ELSE NULL END)
SUM(case when table6.status != 3 THEN 1 ELSE NULL END)
Tables 5 and 6 are empty
This is the latest thing I have tried, I hope it is clear:
SELECT table1.*, COUNT(distinct tbl3.id), SUM(table2.count::int), (SUM(table2.count::int) - SUM(table4.count::int))
, COUNT(table5.count), COUNT(table6.count)
FROM table1
LEFT JOIN table2
ON (table1.id = table2.table1_id AND table2.deleted_at IS NULL)
LEFT JOIN (
SELECT distinct table3.id, table3.table1_id, table3.deleted_at,
SUM(table4.total_count::int),
COUNT(case when table6.status != 3 THEN 1 ELSE NULL END),
COUNT(case when table6.status = 3 THEN 1 ELSE NULL END)
FROM table3
LEFT JOIN table4 ON (table3.id = table4.visa_id AND table4.deleted_at IS NULL)
LEFT JOIN (
SELECT table5.id, table5.table4_id,
COUNT(case when table6.status != 3 THEN 1 ELSE 0 END),
COUNT(case when table6.status = 3 THEN 1 ELSE 0 END)
FROM table5
LEFT JOIN table6 ON (table5.id = table6.table5_id AND table6.deleted_at IS NULL)
GROUP BY 1
) tbl3 ON table4.id = table5.table4_id
WHERE table2.deleted_at IS NULL
GROUP BY 1
) tbl2 ON (table1.id = tbl2.table1_id AND tbl2.deleted_at IS NULL);
The result I get based on the data added on top and the above query:
table1_id
table1_name
SUM(table2_count)
SUM(table4_count)
SUM(table5_count)
SUM(case when table6.status = 3 THEN 1 ELSE NULL END)
SUM(case when table6.status != 3 THEN 1 ELSE NULL END)
1
first_row
3
32
18
2
2
I do not get any errors but all the count come out wrong, either doubled or tripled and sometimes completely wrong (not even just doubled or something).
TABLE:
id second_id status
1 2 1
2 1 0
1 3 1
3 1 1
1 4 1
4 1 1
I try to select only this unique value where the pair have the same status
OUTPUT:
id second_id status
1 3 1
1 4 1
I try with
SELECT table.id, table.second_id, table.status FROM table
WHERE table.id = 1 and table.status = 1
but this return of course bad results ;)
Thx for help :)
One way to do this is to JOIN the table to itself, looking for matching id and second_id values with the same status. We also check that the second table's id value is greater than the first to avoid duplicates:
SELECT t1.*
FROM test t1
JOIN test t2 ON t2.id = t1.second_id
AND t2.second_id = t1.id
AND t2.status = t1.status
AND t2.id > t1.id
Output:
id second_id status
1 3 1
1 4 1
Demo on dbfiddle
One method uses exists:
select t.*
from t
where exists (select 1
from t t2
where t2.second_id = t.id and
t2.id = t.second_id and
t2.status = t.status
);
Or, expressing this using in and tuples is simpler:
select t.*
from t
where (id, second_id, status) in
(select second_id, id, status from t);
if I have a table with values like this:
ID SUBID FLAG
-----------------
1 1 1
1 2 (null)
2 3 1
2 3 (null)
3 4 1
4 5 1
4 6 (null)
5 7 0
6 8 (null)
7 9 1
and I would like to get all the ID's where 'FLAG' is only set to 1, so in this case the query would return
ID SUBID FLAG
-----------------
3 4 1
7 9 1
How can I achieve this?
try this:
SELECT * FROM flags where flag=1
and ID NOT in( SELECT ID FROM flags where flag !=1 OR flag IS NULL)
I don't have a db2 instance to test on but this might work:
select t1.id, t1.subid, t1.flag
from yourtable t1
inner join
(
select id
from yourtable
group by id
having count(id) = 1
) t2
on t1.id = t2.id
where t1.flag = 1;
My question is this: Is it possible to output multiple rows when joining from the same table?
With this code for example, I would like it to output 2 rows, one for each table. Instead, what it does is gives me 1 row with all of the data.
SELECT t1.*, t2.*
FROM table t1
JOIN table t2
ON t2.id = t1.oldId
WHERE t1.id = '1'
UPDATE
Well the problem that I have with the UNION/UNION ALL is this: I don't know what the t1.oldId value is equal to. All I know is the id for t1. I am trying to avoid using 2 queries so is there a way I could do something like this:
SELECT t1.*
FROM table t1
WHERE t1.id = '1'
UNION
SELECT t2.*
FROM table t2
WHERE t2.id = t1.oldId
SAMPLE DATA
messages_users
id message_id user_id box thread_id latest_id
--------------------------------------------------------
8 1 1 1 NULL NULL
9 2 1 2 NULL 16
10 2 65 1 NULL 15
11 3 65 2 2 NULL
12 3 1 1 2 NULL
13 4 1 2 2 NULL
14 4 65 1 2 NULL
15 5 65 2 2 NULL
16 6 1 1 2 NULL
Query:
SELECT mu.id FROM messages_users mu
JOIN messages_users mu2 ON mu2.latest_id IS NOT NULL
WHERE mu.user_id = '1' AND mu2.user_id = '1' AND ((mu.box = '1'
AND mu.thread_id IS NULL AND mu.latest_id IS NULL) OR mu.id = mu2.latest_id)
This query fixes my problem. But it seems the answer to my question is to not use a JOIN but a UNION.
You mean one row for t1 and one row from t2?
You're looking for UNION, not JOIN.
select * from table where id = 1
union
select * from table where oldid = 1
If you are trying to multiply rows in a table, you need UNION ALL (not UNION):
select *
from ((select * from t) union all
(select * from t)
) t
I also sometimes use a cross join to do this:
select *
from t cross join
(select 1 as seqnum union all select 2) vals
The cross join is explicitly multiplying the number of rows, in this case, with a sequencenumber attached.
Well, since it's the same table, you could do:
SELECT t2.*
FROM table t1
JOIN table t2
ON t2.id = t1.oldId
OR t2.id = t1.id
WHERE t1.id = '1'
Consider tables
Table1
id, name
1 xyz
2 abc
3 pqr
Table2
id title
1 Mg1
2 Mg2
3 SG1
Table3
Tb1_id tb2_id count
1 1 3
1 2 3
1 3 4
2 2 1
3 2 2
3 3 2
I want to do query to give result like
id title
1 MG1
2 MG2
3 Two or More Title
MG1 has higher preference if MG1 and count >= 1 then it is given as MG1 title , for others corresponding title is used and for count > 1 as two or more
I think this is what you are going for:
select t3.Tb1_id as id,
case
when mg1cnt.count >= 1 then 'MG1'
when cnt.count = 1 then upper(t2.title)
else 'Two or More Titles'
end as title
from (
select Tb1_id, count(*) as count
from Table3
group by Tb1_id
) cnt
inner join (
select Tb1_id, isnull(SUM(case when t2.title='mg1' then 1 end), 0) as count
from Table3 t3
inner join Table2 t2 on t3.tb2_id = t2.id
group by Tb1_id
) as mg1cnt on cnt.Tb1_id = mg1cnt.Tb1_id
inner join Table3 t3 on cnt.Tb1_id = t3.Tb1_id
inner join Table2 t2 on t3.tb2_id = t2.id
group by t3.Tb1_id,
case
when mg1cnt.count >= 1 then 'MG1'
when cnt.count = 1 then upper(t2.title)
else 'Two or More Titles'
end