Getting Records from SQL Table by checking Multiple Columns - sql

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

Joining Multiple Tables While Showing Correct COUNT and SUM Data

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).

How to select unique value from two columns if third have the same value

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);

DB2 sql group by/count distinct column values

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;

SQL: Outputting Multiple Rows When Joining From Same Table

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'

Design SQL Query for following case

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