Check for same ID in 3 different tables - sql

Hi all I have the following query to check if an ID is present in a table:
SELECT CASE WHEN EXISTS (SELECT 1 FROM (SELECT TOP 1 RequestID FROM tT
UNION
SELECT TOP 1 RequestID FROM tET
UNION
SELECT TOP 1 RequestID FROM tE) AS idSearcher
WHERE
idSearcher.RequestID = 120) THEN 'y' ELSE 'n' END AS alreadyHasID
This works but it doesn't seem to see if ANY of the 3 tables have the same ID. The above query only seems to check if ALL of the 3 tables has that value.
As an example the output for the query above:
|alreadyHasID |
+-------------+
n
When it should be 'y' since, out of the 3 tables, 1 table DOES have 120.
Running each of the 3 tables separately gives this as the output:
+----------+
|tT |
+----------+
no records
+----------+
|tET |
+----------+
no records
+----------+
|tE |
+----------+
120
How can this be modified in order to show a "y" if it finds the ID in ANY of the 3 tables?

Use inner joins to filter where there is a match for ALL:
SELECT CASE WHEN EXISTS(
SELECT *
FROM (tT INNER JOIN tET ON tT.RequestID = tET.RequestID)
INNER JOIN tE ON tT.RequestID = tE.RequestID
WHERE tT.RequestID = 120
) THEN 'y' ELSE 'n' END AS alreadyHasID
For ANY you do it this way:
SELECT CASE WHEN EXISTS(SELECT * FROM tT WHERE [RequestID] = 120) THEN 'y'
WHEN EXISTS(SELECT * FROM tET WHERE RequestID = 120) THEN 'y'
WHEN EXISTS(SELECT * FROM tE WHERE RequestID = 120) THEN 'y' ELSE 'n' END as [alreadyHasID]

select case
when exists (select 1 from tT where RequestID = 120)
or exists (select 1 from tTE where RequestID = 120)
or exists (select 1 from tE where RequestID = 120)
then 'y'
else 'n'
end

I assume you meant "to show a y if it finds the ID in ALL tables".
May be something like this:
select case when (
select count(case when RequestID = 120 then 1 end)
from (
select * from (select top 1 RequestID
from tT
order by ??)
union all
(select top 1 RequestID
from tET
order by ??)
union all
(select top 1 RequestID
from tE
order by ??)
) as t
) = 3 then 'y' else 'n' end as alreadyHasID
Note the added order by. You should always add these when using TOP queries.

This is so messed up
TOP is non deterministic
You are checking idSearcher.RequestID = 120 outside
SELECT CASE WHEN EXISTS (SELECT 1 FROM ( SELECT TOP 1 RequestID FROM tT
UNION
SELECT TOP 1 RequestID FROM tET
UNION
SELECT TOP 1 RequestID FROM tE
) AS idSearcher
WHERE idSearcher.RequestID = 120
)
THEN 'y' ELSE 'n' END AS alreadyHasID

Related

How to merge two query results joining same date

let's say there's a table have data like below
id
status
date
1
4
2022-05
2
3
2022-06
I want find count of id of each month by their status. Something like this below
date
count(status1) = 4
count(status2) =3
2022-05
1
null
2022-06
null
1
I tried doing
-- select distinct (not working)
select date, status1, status2 from
(select date, count(id) as "status1" from myTable
where status = 4 group by date) as myTable1
join
(select date, count(id) as "status2" from myTable
where status = 3 group by date) as myTable2
on myTable1.date = myTable2.date;
-- group by (not working)
but it does duplicate the data needed.
and I am using SQL Server.
select d.date,
sum
(
case
when d.status=4 then 1
else 0
end
)count_status_4,
sum
(
case
when d.status=5 then 1
else 0
end
)count_status_5
from your_table as d
group by d.date

Oracle SQL: How to select only ID‘s which are member in specific groups?

I want to select only those ID‘s which are in specific groups.
For example:
ID GroupID
1 11
1 12
2 11
2 12
2 13
Here I want to select the ID's which are in the groups 11 and 12 but in no other groups.
So the result should show just the ID 1 and not 2.
Can someone provide a SQL for that?
I tried it with
SELECT ID FROM table
WHERE GroupID = 11 AND GroupID = 12 AND GroupID != 13;
But that didn't work.
You can use aggregation:
select id
from mytable
group by id
having min(groupID) = 11 and max(groupID) = 12
This having condition ensures that the given id belongs to groupIDs 11 and 12, and to no other group. This works because 11 and 12 are sequential numbers.
Other options: if you want ids that belong to group 11 or 12 (not necessarily both), and to no other group, then:
having sum(case when groupId in (11, 12) then 1 end) = count(*)
If numbers are not sequential, and you want ids in both groups (necessarily) and in no other group:
having
max(case when groupID = 11 then 1 end) = 1
and max(case when groupID = 12 then 1 end) = 1
and max(case when groupID in (11, 12) then 0 else 1 end) = 0
SELECT t.id FROM table t
where exists(
SELECT * FROM table
where group = 11
and t.id = id
)
and exists(
SELECT * FROM table
where group = 12
and t.id = id
)
and not exists(
SELECT * FROM table
where group = 13
and t.id = id
)
group by t.id
One method is conditional aggregation:
select id
from t
group by id
having sum(case when groupid = 1 then 1 else 0 end) > 0 and
sum(case when groupid = 2 then 1 else 0 end) > 0 and
sum(case when groupid in (1, 2) then 1 else 0 end) = 0 ;
You can use GROUP BY with HAVING and a conditional COUNT:
SELECT id
FROM table_name
GROUP BY ID
HAVING COUNT( CASE Group_ID WHEN 11 THEN 1 END ) > 0
AND COUNT( CASE Group_ID WHEN 12 THEN 1 END ) > 0
AND COUNT( CASE WHEN Group_ID NOT IN ( 11, 12 ) THEN 1 END ) = 0
Or you can use collections:
CREATE TYPE int_list IS TABLE OF NUMBER(8,0);
and:
SELECT id
FROM table_name
GROUP BY id
HAVING int_list( 11, 12 ) SUBMULTISET OF CAST( COLLECT( group_id ) AS int_list )
AND CARDINALITY( CAST( COLLECT( group_id ) AS int_list )
MULTISET EXCEPT int_list( 11, 12 ) ) = 0
(Using collections has the advantage that you can pass the collection of required values as a single bind parameter whereas using conditional aggregation is probably going to require dynamic SQL if you want to pass a variable number of items to the query.)
Both output:
| ID |
| -: |
| 1 |
db<>fiddle here
Use joins:
SELECT DISTINCT c11.ID
FROM (SELECT ID FROM WORK_TABLE WHERE GROUPID = 11) c11
INNER JOIN (SELECT ID FROM WORK_TABLE WHERE GROUPID = 12) c12
ON c12.ID = c11.ID
LEFT OUTER JOIN (SELECT ID FROM WORK_TABLE WHERE GROUPID NOT IN (11, 12)) co
ON co.ID = c11.ID
WHERE co.ID IS NULL;
The INNER JOIN between the first two subqueries ensures that rows exist for both GROUPID 11 and 12, and the LEFT OUTER JOIN and WHERE verify that there are no rows for any other GROUPIDs.
dbfiddle here

TSQL - Select rows with same column A but different column B

I'm trying to find rows (Name) that does not have ID = 1. For example, if my table looked like this:
Name ID
--------------
A 1
A 0
B 1
B 0
C 0
D 2
D 0
The answer to this query would be:
Name
-----
C
D
Do you have any idea?
SELECT Name
FROM myTable
GROUP BY Name
HAVING SUM(CASE WHEN ID = 1 THEN 1 ELSE 0 END) = 0
Here is one way to do it:
SELECT DISTINCT Name
FROM Table t0
WHERE NOT EXISTS
(
SELECT 1
FROM Table t1
WHERE t0.Name = t1.Name
AND t1.Id = 1
)
Try this query:
SELECT DISTINCT(name)
FROM tbl t1
WHERE
NOT EXISTS (SELECT name FROM tbl t2 WHERE ID=1 AND t1.name=t2.name)
Select Distinct name
From myTable
Where name not in (Select name From myTable Where id= 1)

Any other alternative to write this SQL query

I need to select data base upon three conditions
Find the latest date (StorageDate Column) from the table for each record
See if there is more then one entry for date (StorageDate Column) found in first step for same ID (ID Column)
and then see if DuplicateID is = 2
So if table has following data:
ID |StorageDate | DuplicateTypeID
1 |2014-10-22 | 1
1 |2014-10-22 | 2
1 |2014-10-18 | 1
2 |2014-10-12 | 1
3 |2014-10-11 | 1
4 |2014-09-02 | 1
4 |2014-09-02 | 2
Then I should get following results
ID
1
4
I have written following query but it is really slow, I was wondering if anyone has better way to write it.
SELECT DISTINCT(TD.RecordID)
FROM dbo.MyTable TD
JOIN (
SELECT T1.RecordID, T2.MaxDate,COUNT(*) AS RecordCount
FROM MyTable T1 WITH (nolock)
JOIN (
SELECT RecordID, MAX(StorageDate) AS MaxDate
FROM MyTable WITH (nolock)
GROUP BY RecordID)T2
ON T1.RecordID = T2.RecordID AND T1.StorageDate = T2.MaxDate
GROUP BY T1.RecordID, T2.MaxDate
HAVING COUNT(*) > 1
)PT ON TD.RecordID = PT.RecordID AND TD.StorageDate = PT.MaxDate
WHERE TD.DuplicateTypeID = 2
Try this and see how the performance goes:
;WITH
tmp AS
(
SELECT *,
RANK() OVER (PARTITION BY ID ORDER BY StorageDate DESC) AS StorageDateRank,
COUNT(ID) OVER (PARTITION BY ID, StorageDate) AS StorageDateCount
FROM MyTable
)
SELECT DISTINCT ID
FROM tmp
WHERE StorageDateRank = 1 -- latest date for each ID
AND StorageDateCount > 1 -- more than 1 entry for date
AND DuplicateTypeID = 2 -- DuplicateTypeID = 2
You can use analytic function rank , can you try this query ?
Select recordId from
(
select *, rank() over ( partition by recordId order by [StorageDate] desc) as rn
from mytable
) T
where rn =1
group by recordId
having count(*) >1
and sum( case when duplicatetypeid =2 then 1 else 0 end) >=1

How to get require output using order by?

Could you help me, i am expecting output is,
select * from table order by value
Output:
Value
E1
E2
O
R
Required Output:
R
E1
E2
O
Try this
SELECT * FROM yourTable
ORDER BY CASE WHEN VALUE = 'R' Then 1 Else 0 End,Value ASC
If you are using UNION then try this
SELECT * FROM
(
SELECT *
FROM table1
UNION ALL
SELECT *
FROM table2
) T
ORDER BY CASE WHEN VALUE = 'R' Then 1 Else 0 End,Value ASC
a bit of a hack but if that's what you want...
order by
case when value='r' then 1
when value='e1' then 2
when value='e2' then 3
when value='o' then 4 end
Try
SELECT *
FROM table1
ORDER BY CASE
WHEN value = 'R' THEN 0
WHEN value LIKE 'E%' THEN 1
WHEN value = 'O' THEN 2
END, LEN(value), value
Output:
| VALUE |
|-------|
| R |
| E1 |
| E2 |
| O |
Here is SQLFiddle demo
...if i using union all operator for merging two table, its showing error...
With UNION you can do
SELECT *
FROM
(
SELECT *
FROM table1
UNION ALL
SELECT *
FROM table2
) q
ORDER BY CASE
WHEN value = 'R' THEN 0
WHEN value LIKE 'E%' THEN 1
WHEN value = 'O' THEN 2
END, LEN(value), value