Not exists query is not returning expected info - sql

I have a query, and for some reason I'm not getting the orderid 10 info as expected. The results give no lines. The query without the not exists part gives the below info.
The table looks like this:
orderid id number fulfilledproduct
2 BundleSpec 1 ID
2 TemplateSpec 1 IDSheet
2 TemplateSpec 1 IDCertificate
10 BundleSpec 1 ID
10 TemplateSpec 1 IDSheet
For some reason my query returns 0 lines when I try to get the orderid without the IDCertificate.
It's probably something I need to fix for the not exists part since I don't do that very often. Any ideas?
select (orderid),(id),(number),(fulfilledproduct)
from [Product]
where
id in ('BundleSpec','TemplateSpec')
and not exists
(
select (orderid)
from [Product]
where
id in ('BundleSpec','TemplateSpec')
and fulfilledproduct = 'IDCertificate'
)
I thought I was following an example correctly. Should I use except instead like except does?
Expected Output:
orderid id number fulfilledproduct
10 BundleSpec 1 ID
10 TemplateSpec 1 IDSheet
Note that this is using a dlx sql command on a device at the command line, and my example had the () and [] for the table info in the query so I'm using that too. It should give output the same way microsoft sql works in sql server as I am told. I have formatted the query for easy viewing and removed the command line syntax.

This is because your not-exists clause has nothing tying it to the main query. Your not-exists query always returns a row, so therefore the main query returns nothing.
You need to tell it something like this:
select (orderid),(id),(number),(fulfilledproduct)
from [Product] p
where
id in ('BundleSpec','TemplateSpec')
and not exists
(
select 1
from [Product] p2
where
p2.orderid = p.orderid
and p2.fulfilledproduct = 'IDCertificate'
)

Related

Why aren't these two sql statements returning same output?

I'm just getting started with sql and have the objective to transform this:
select X.persnr
from Pruefung X
where X.persnr in (
select Y.persnr
from pruefung Y
where X.matrikelnr <> Y.matrikelnr)
output:
into the same output but using a form of join. I tried it the way below but I can't seem to get "rid" of the cartesian product as far as i can see. Or maybe i misunderstood the above statement what it should actually do. For me the above says "for each unique matrikelnr display all corresponding persnr".
select X.persnr
from Pruefung X
join pruefung y on x.persnr=y.persnr
where x.matrikelnr<>y.matrikelnr
output: A long list (I don't want to fill the entire question with it) - i am guessing the cartesian product from the join
This is the relation I am using.
Edit: Distinct (unless i am using it in the wrong place) won't work because then persnr is only displayed once, thats not the objective though.
Your initial query actually does:
select persnr from Pruefung if the same persnr exists for a a diferent matrikelnr.
"for each unique matrikelnr display all corresponding persnr"
This is achieved using aggregation:
Depending on the DBMS you are using you could use something like (SQL Server uses STRING_AGG, but MySQL uses GROUP_CONCAT)
SELECT matrikelnr,STRING_AGG(matrikelnr,',')
GROUP BY matrikelnr
You cannot easily achieve what you got from a correlated query (your first attempt) by using a join.
Edit:
A join does not result in a "Cartesian product" expect from when there is no join condition (CROSS JOIN).
A join matches two sets based on a join condition. The reason why you get more entries is that the join looks at the join key (PERSNR) and does its matching.
For example for 101 you have 3 entries. That means you will get 3x3 reults.
You then filter out the results for the cases where X.matrikelnr <> Y.matrikelnr If we assume matrikelnr is unique that would mean the row matched with itself. so you will lose 3 results ending up with 3x3 - 3 = 6.
If you want to achieve something in SQL you must first define what you are expecting to use and then use the appropiate tools (in this case correlated queries not joins)
You can write your 1st query with EXISTS instead of IN like:
select X.persnr
from Pruefung X
where exists (
select 1
from pruefung Y
where X.persnr = Y.persnr and X.matrikelnr <> Y.matrikelnr
)
This way it's obvious that this query means:
return all the persnrs of the table for which there exists another
row with the same persnr but different matrikelnr
For your sample data the result is all the persnrs of the table.
Your 2nd query though, does something different.
It links every row of the table with all the rows of the same table with the same persnr but different matrikelnr.
So for every row of the table you will get as many as rows as there are for the same persnrs but different matrikelnrs.
For example for the 1st row with persnr = 101 and matrikelnr = 8532478 you will get 2 rows because there are 2 rows in the table with persnr = 101 and matrikelnr <> 8532478.
You are right. It's the cartesian product's fault. Suppose you have persnr 1,1,1,2,2,2 in the first table and persnr 1,1,1,2,2 in the second. How many lines are you expecting to be returned?
In pdeuso-code it would go like this
Select
...
WHERE persnr in (second table)
-- 6 lines
Select persnr
FROM ...
JOIN ... ON a.persnr = b.persnr
-- 3X3 + 3X2 = 15 lines.
SELECT DISTINCT persnr
FROM ...
JOIN ... ON a.persnr = b.persnr
-- 2 lines (1 and 2)
Take your pick

SQL: How to select and sum up columns in this query?

I have been looking but not finding my precise case so I try asking here.
There is a query (which I unfortunately may not disclose) that has this structure:
WITH MAINRESULT AS
(
SELECT ... FROM ... WHERE...GROUP BY...
)
SELECT Name, SUM(MAINRESULT.Amount1 * AnotherAmount) AS MySum FROM MAINRESULT
WHERE .....
GROUP BY Name, AnotherAmount
ORDER BY Name
Now, I get something like this:
**Name** **MySum**
A 5
A 5
B 1
C 2
But I want to have this result SUM-med up so that I get:
**Name** **MySum**
A 10
B 1
C 2
How do I do this by modifying the query struture that I have?
Tried adding a "SELECT FROM" around both the WITH-query parn and the Second SELECT below it but it says I have syntax errors then.
UPDATE:
I had been staring for too long at that Query I missed that the AnotherAmount should not be included in the GROUP BY part. Thanks everyone for pointing it out so quickly!
It looks like you need to remove GROUP BY Name, AnotherAmount and left only GROUP BY Name in your query. Otherwise your results being groupped not only by Name but also by some AnotherAmount field - this may cause unexpected result you're getting.

SQL - How to update a field in a record to summed value from two tables

I'm having a problem getting a table to update and am hoping that maybe someone here can help me out. I'm just learning SQL, so I'm not sure of the best way to do certain processes. I have a value in one of my tables that somehow got out of whack. Now, I need to update it using the original value minus the sum of values in a different table.
Table 1 is ORDER_LINES.
ORDER_NO QTY_ON_ORD ORIG_ORD_QTY
0900476 10 100
Table 2 is INVOICED_LINES.
INV_NO SHIP_QTY ORIG_ORD_NO
000441 20 0900476
000441 25 0900476
000441 15 0900476
000441 10 0900476
Value of ORDER_LINES.QTY_ON_ORD should be:
ORDER_LINES.QTY_ON_ORD =
ORDER_LINES.ORIG_ORD_QTY - SUM(INVOICED_LINES.SHIP_QTY)
WHERE INVOICED_LINES.ORIG_ORD_NO = ORDER_LINES.ORDER_NO
So, the value of ORDER_LINES.QTY_ON_ORD is not correct. The values in these are constantly changing, so I'd like to have a SQL command that I can run to update these on the fly. I've tried many things such as:
UPDATE "ORDER_LINES"
SET QTY_ON_ORD = SELECT (
(SELECT SUM(ORIG_ORD_QTY) FROM "ORDER_LINES" WHERE ORDER_NO = '0900476') -
(SELECT SUM(SHIP_QTY) FROM "INVOICED_LINES" WHERE ORIG_ORD_NO = '0900476')
)
WHERE ORDER_NO = '0900476';
But that doesn't work. The Selects by themselves print out the correct qty in my query, but I can't seem to use that qty in my update.
We're running Pervasive SQL if that makes any difference.

SQL list multiple Duplicates

running a SQL query in access that is giving me matches where A = record 1, and B also = record 1 , C= record 2 and D E and F also = record 2.
I want my results to display (only max Value)
B =record 1
F= record 2. ( this is a matching query)
basically i want to eliminate duplicates and select "distinct" does not seem to be working for me.
SELECT
FEED_2.ID AS FEED_2_ID,
FEED_3.field_ID,
FEED_3.ID AS FEED_3_ID
FROM FEED_2 INNER JOIN FEED_3 ON FEED_2.[field_ID] = FEED_3.[field_ID]
order by FEED_3.ID
im getting results where feed 2 ID #1,3, and 5 all equal feed 3 - ID #1
i only want feed 2, #5 = feed 3 #1. no Dupes
sorry - hope that helps
It's a shot in the dark but, is something like this you are looking for?
SELECT max(Column_With_ABCDEF), Column_With_record from TABLE_NAME GROUP BY Column_With_record;
If this is not what you are asking for, please do edit your question with your table schema and/or the query you are using so we can help.
---------------- EDIT ----------------
Ok so you can try this:
Select max(FEED_2_ID), field_ID , FEED_3_ID
from (
SELECT FEED_2.ID AS FEED_2_ID, FEED_3.field_ID As field_ID, FEED_3.ID AS FEED_3_ID
FROM FEED_2 INNER JOIN FEED_3
ON FEED_2.[field_ID] = FEED_3.[field_ID]
)
GROUP BY FEED_3_ID, field_ID
ORDER BY FEED_3_ID
The main select is going to group the result from the subquery, that way you should not get duplicated values.
Hope this help

How do I preserve the order of a SQL query using the IN command

SELECT * FROM tblItems
WHERE itemId IN (9,1,4)
Returns in the order that SQL finds them in (which happens to be 1, 4, 9) however, I want them returned in the order that I specified in the array.
I know I could reorder them after in my native language (obj c), but is there a neat way to do this in SQL?
Somthing like this would be great:
ORDER BY itemId (9,1,4) -- <-- this dosn't work :)
Probably the best way to do this is create a table of item IDs, which also includes a rank order. Then you can join and sort by the rank order.
Create a table like this:
itemID rank
9 1
1 2
4 3
Then your query would look like this:
select tblItems.* from tblItems
inner join items_to_get on
items_to_get.itemID = tblItems.itemID
order by rank
Use a CASE expression to map the ID values to an increasing sequence:
... ORDER BY CASE itemId
WHEN 9 THEN 1
WHEN 1 THEN 2
ELSE 3
END
I had the same task once in a mysql environment.
I ended up using
ORDER BY FIND_IN_SET(itemID, '9,1,4')
this is working for me since then. I hope it also works for sqlite
You can add a case construct to your select clause.
select case when itemid = 9 then 1
when itemid = 1 then 2 else 3 end sortfield
etc
order by sortfield
You could create a procedure to order the data in SQL, but that would be much more complicated than its native language counterpart.
There's no "neat way" to resort the data like that in SQL -- the WHERE clause of a SELECT simply says "if these criteria are matched, include the row"; it's not (and it cannot be) an ordering criterion.