Find ID's not match a list - sql

I cannot say I am so experienced with SQL. Here is my question.
A table TripEvent have millions of rows. It contains a column Bold_ID that is indexed and unique.
So I can have this query
select bold_id from TripEvent where bold_id in (354469477, 354469536, 354469500, 987359)
Result is
354469477
354469536
354469500
as those exists. But I want to reverse it. How can I get a list if id's that don't exists ?
In this case it should return one row
987359
I cannot use NOT in query as that would return all rows in table not match my list.

One way is like this:
SELECT DS.*
FROM
(
VALUES (354469477)
,(354469536)
,(354469500)
,(987359)
) DS (bold_id)
LEFT JOIN TripEvent TE
ON DS.[bold_id] = TE.[bold_id]
WHERE TE.[bold_id] IS NULL;
Of course, there are diff ways to populated the DS. I will recommend to populate the search IDs in a temporary table.

Since you are using a SQL Server DB, you can use EXCEPT:
SELECT bold_id FROM
(
SELECT 354469477 AS bold_id
UNION ALL
SELECT 354469536
UNION ALL
SELECT 354469500
UNION ALL
SELECT 987359
) listofValues
EXCEPT
SELECT bold_id
FROM TripEvent;
OR:
SELECT bold_id FROM
(
VALUES (354469477),
(354469536),
(354469500),
(987359)
) listofValues(bold_id)
EXCEPT
SELECT bold_id
FROM TripEvent;
Have a look in the documentation

Found this query on another places. Seems to work. Thanks for the good response :)
SELECT *
from (values (354469477),(354469536),(354469500),(987359)) as v(id)
WHERE NOT EXISTS (SELECT BOLD_ID FROM TripEvent WHERE TripEvent.BOLD_ID = v.id)

Related

Query to show all ID's except the ones that have a specific instrument

So I have a table which looks like this:
What would be the best query to exclude every "stuknr" that has atleast 1 "saxofoon" in the "instrumentnaam" column?
To select all stuknr where there is not stuknr with a saxofoon:
SELECT *
FROM table
WHERE stuknr not in (
SELECT stuknr
FROM TABLE
WHERE INSTRUMENTNAAM = ‘saxofoon’)
;
SELECT STUNKR
FROM TABLE
WHERE INSTRUMENTNAAM != ‘saxofoon’;
Here != (or <>, which are equivalent, see this) means "not equal".
You can do this with a NOT IN sub-select
select distinct
YT.stunkr
from
YourTable YT
where YT.stunkr NOT IN ( select distinct stunkr
from YourTable
where InstrumentNaam = 'saxofoon' )
So the sub-select is getting all IDs that DO have saxofoon and the primary select/from is getting where the ID is NOT in the secondary.

Order by data as per supplied Id in sql

Query:
SELECT *
FROM [MemberBackup].[dbo].[OriginalBackup]
where ration_card_id in
(
1247881,174772,
808454,2326154
)
Right now the data is ordered by the auto id or whatever clause I'm passing in order by.
But I want the data to come in sequential format as per id's I have passed
Expected Output:
All Data for 1247881
All Data for 174772
All Data for 808454
All Data for 2326154
Note:
Number of Id's to be passed will 300 000
One option would be to create a CTE containing the ration_card_id values and the orders which you are imposing, and the join to this table:
WITH cte AS (
SELECT 1247881 AS ration_card_id, 1 AS position
UNION ALL
SELECT 174772, 2
UNION ALL
SELECT 808454, 3
UNION ALL
SELECT 2326154, 4
)
SELECT t1.*
FROM [MemberBackup].[dbo].[OriginalBackup] t1
INNER JOIN cte t2
ON t1.ration_card_id = t2.ration_card_id
ORDER BY t2.position DESC
Edit:
If you have many IDs, then neither the answer above nor the answer given using a CASE expression will suffice. In this case, your best bet would be to load the list of IDs into a table, containing an auto increment ID column. Then, each number would be labelled with a position as its record is being loaded into your database. After this, you can join as I have done above.
If the desired order does not reflect a sequential ordering of some preexisting data, you will have to specify the ordering yourself. One way to do this is with a case statement:
SELECT *
FROM [MemberBackup].[dbo].[OriginalBackup]
where ration_card_id in
(
1247881,174772,
808454,2326154
)
ORDER BY CASE ration_card_id
WHEN 1247881 THEN 0
WHEN 174772 THEN 1
WHEN 808454 THEN 2
WHEN 2326154 THEN 3
END
Stating the obvious but note that this ordering most likely is not represented by any indexes, and will therefore not be indexed.
Insert your ration_card_id's in #temp table with one identity column.
Re-write your sql query as:
SELECT a.*
FROM [MemberBackup].[dbo].[OriginalBackup] a
JOIN #temps b
on a.ration_card_id = b.ration_card_id
order by b.id

SQL Logic: Finding Non-Duplicates with Similar Rows

I'll do my best to summarize what I am having trouble with. I never used much SQL until recently.
Currently I am using SQL Server 2012 at work and have been tasked with trying to find oddities in SQL tables. Specifically, the tables contain similar information regarding servers. Kind of meta, I know. So they each share a column called "DB_NAME". After that, there are no similar columns. So I need to compare Table A and Table B and produce a list of records (servers) where a server is NOT listed in BOTH Table A and B. Additionally, this query is being ran against an exception list. I'm not 100% sure of the logic to best handle this. And while I would love to get something "extremely efficient", I am more-so looking at something that just plain works at the time being.
SELECT *
FROM (SELECT
UPPER(ta.DB_NAME) AS [DB_Name]
FROM
[CMS].[dbo].[TABLE_A] AS ta
UNION
SELECT
UPPER(tb.DB_NAME) AS [DB_Name]
FROM
[CMS].[dbo].[TABLE_B] as tb
) AS SQLresults
WHERE NOT EXISTS (
SELECT *
FROM
[CMS].[dbo].[TABLE_C_EXCEPTIONS] as tc
WHERE
SQLresults.[DB_Name] = tc.DB_NAME)
ORDER BY SQLresults.[DB_Name]
One method uses union all and aggregation:
select ab.*
from ((select upper(name) as name, 'A' as which
from CMS.dbo.TABLE_A
) union all
(select upper(name), 'B' as which
from CMS.dbo.TABLE_B
)
) ab
where not exists (select 1
from CMS.dbo.TABLE_C_EXCEPTION e
where upper(e.name) = ab.name
)
having count(distinct which) <> 2;
SQL Server is case-insensitive by default. I left the upper()s in the query in case your installation is case sensitive.
Here is another option using EXCEPT. I added a group by in each half of the union because it was not clear in your original post if DB_NAME is unique in your tables.
select DatabaseName
from
(
SELECT UPPER(ta.DB_NAME) AS DatabaseName
FROM [CMS].[dbo].[TABLE_A] AS ta
GROUP BY UPPER(ta.DB_NAME)
UNION ALL
SELECT UPPER(tb.DB_NAME) AS DatabaseName
FROM [CMS].[dbo].[TABLE_B] as tb
GROUP BY UPPER(tb.DB_NAME)
) x
group by DatabaseName
having count(*) < 2
EXCEPT
(
select DN_Name
from CMS.dbo.TABLE_C_EXCEPTION
)

differentiate rows in a union table

I m selecting data from two different tables with no matching columns using this sql query
select * from (SELECT s.shout_id, s.user_id, s.time FROM shouts s
union all
select v.post_id, v.sender_user_id, v.time from void_post v)
as derived_table order by time desc;
Now is there any other way or with this sql statement only can i
differentiate the data from the two tables.
I was thinking of a dummy row that can be created at run-time(in the select statement only ) which would flag the row from the either tables.
As there is no way i can differentiate the shout_id that is thrown in the unioned table is
shout_id from the shout table or from the void_post table.
Thanks
Pradyut
You can just include an extra column in each select (I'd suggest a BIT)
select * from
(SELECT s.shout_id, s.user_id, s.time, 1 AS FromShouts FROM shouts s
union all
select v.post_id, v.sender_user_id, v.time, 0 AS FromShouts from void_post v)
as derived_table order by time desc;
Sure, just add a new field in your select statement called something like source with a different constant value for each source.
SELECT s.shout_id, s.user_id, s.time, 'shouts' as source FROM shouts s
UNION ALL
SELECT v.post_id, v.sender_user_id, v.time, 'void_post' as source FROM void_post v
A dummy variable is a nice way to do it. There isn't much overhead in the grand scheme of things.
p.s., the dummy variable represents a column and not a row.

Reducing the recordset where a particular field has similar data. (MySQL)

I have two tables, 'discussion' and 'discussion_responses'. A unique ID from 'discussion' is used in 'discussion_responses' to identify the response to the original post in a forum. I created the following query to extract the posts that have NEW replies, but are NOT linked to new topics. Both tables have a field for the date added and 'colname' is Dreamweaver's variable name for the visitor's last log-in date retrieved from another table:
SELECT *
FROM discussion, discussion_responses
WHERE discussion.discussion_date < colname
AND discussion_responses.discussion_date > colname
AND discussion.discussion_ID = discussion_responses.discussion_ID
ORDER BY discussion.discussion_title ASC
My problem is that where more than one reply has been made to the original post, I naturally get more than one result for that discussion ID. Can anyone please advise me as to how I can eliminate subsequent rows containing the same discussion_ID? It doesn't matter which record is chosen, only that I get the ID of any topic that has had a new reply associated with it. Thanks.
This:
SELECT *
FROM discussion d
WHERE discussion_date < colname
AND EXISTS
(
SELECT NULL
FROM discussion_responses dr
WHERE dr.discussion_date > colname
AND dr.discussion_ID = d.discussion_ID
)
ORDER BY
d.discussion_title ASC
or this:
SELECT d.*
FROM (
SELECT DISTINCT discussion_ID
FROM discussion_responses dr
WHERE dr.discussion_date > colname
)
JOIN discussion d
ON d.discussion_ID = dr.discussion_ID
WHERE d.discussion_date < colname
ORDER BY
d.discussion_title ASC
The latter query will probably be faster, since the condition used in the second query's leading table (discussion_responses) is more selective.
Create an index on discussion_responses (discussion_date, discussion_id).
If you're just interested in the discussion_ID, you could use distinct or group by. Here's an example with distinct:
SELECT DISTINCT discussion_ID
FROM discussion d
INNER JOIN discussion_responses dr
ON d.discussion_ID = dr.discussion_ID
WHERE d.discussion_date < colname
AND dr.discussion_date > colname
If you're also interested in other columns, filter on the distinct id's in a subquery:
SELECT *
FROM discussion d
WHERE d.discussion_ID IN (
<query from above here>
)