Determining if a sample contains 0 rows for multiple ID's - sql

So I've created a simple query that will pass all OrdID's that have orders of 2 or more apples:
SELECT ordid
FROM results
WHERE ordid IN (12,24,53,21,41,51)
AND product = 'apples'
GROUP BY ordid
HAVING COUNT(ordid) > 1
How can I do this for OrdID's that contain 0 apples?(This doesn't work as there is no product on the OrdID by apples, so it passes 0 rows.) I'd like it to list all OrdID's that have < 1 products for Apples.
SELECT ordid
FROM results
WHERE ordid IN (12,24,53,21,41,51)
AND product = 'apples'
GROUP BY ordid
HAVING COUNT(ordid) < 1

I cannot reproduce in my machine but I hope that this query should work:
SELECT ordid
FROM results
WHERE ordid in (12,24,53,21,41,51)
GROUP BY ordid
HAVING SUM(CASE WHEN product = 'apples' THEN 1 ELSE 0 END) < 1

I switched the HAVING with a COUNT() of the products instead of the orderid since youre trying to count the number of products.
SELECT ordid
FROM results
WHERE ordid in (12,24,53,21,41,51) and product = 'apples'
GROUP BY ordid
HAVING COUNT(product) = 0

The problem you're running into is that you're selecting FROM a table (i.e., limiting to those rows) where what you want to match is what's not in the table (i.e., excluding those rows). These are opposites.
Instead, flip that around so you're selecting FROM the set of values and then excluding those that match:
SELECT ordid FROM (VALUES (12),(24),(53),(21),(41),(51)) AS ordids(ordid)
WHERE NOT EXISTS (
SELECT * FROM results
WHERE results.ordid = ordids.ordid
AND results.product = 'apples'
)
This will return a result for an ordid even if that value never appears in the results table at all.

Use the EXISTS() function to get all OrdIDs WHERE there does NOT EXIST a correlated row with product = 'apples'

Related

need an additional column in SQL output

I have a table called product_info where there are two columns(product, product_id).There are 5 'product_id' and 10 'product'. I wrote the following code to list products and their count.Now I need to create an additional column called 'favorite_product' if the 'product' count is more than 3.When I tried with a couple of WHERE clause options, it filtered out my existing column (product_count) which I need to keep intact in the output. How can I do that?
Any help would be appreciated.
SELECT product AS Product_Name,
COUNT (product) AS Product_Count
FROM product_info
GROUP BY product
Just use a case expression:
SELECT product AS Product_Name, COUNT(*) AS Product_Count,
(CASE WHEN COUNT(*) > 3 THEN 1 ELSE 0 END) as is_favorite_flag
FROM product_info
GROUP BY product;

Is it possible to aggregate the results from different rows into just one, along with the count?

So I've got a small DB that has like subsections that come under a single section. Unfortunately, the DB doesn't have a "section" column and just the subsections and they have a "Inventory" column that has either "Computer" or "Laptop" in it. I've made a query that at the very least provides me with the total count of each of these "Inventory" column against each subsection.
However, I'm trying to combine the subsections into a single row and the total count of those subsections alongside it as well. Example of what I'm trying to say:
subsections
inventory
a_subsec1
comp
a_subsec1
comp
a_subsec2
lap
a_subsec2
comp
a_subsec3
lap
a_subsec3
comp
What I'm currently getting:
d_sub
inv_count_comp
a_subsec1
2
a_subsec2
1
a_subsec3
1
What I WANT to get:
D_SUB
total_comp_count
a_sec
4
Here's the query that I'm currently running to get that second table:
SELECT DISTINCT "subsections", COUNT("inventory") FROM mytable WHERE "inventory" = 'comp' GROUP BY "subsections" ORDER BY "subsections" ASC
Thank you.
substring the column then you can treat all the row as same subsection.
with tb as(
select 'a_subsec1' sec,'comp' inv
union all
select 'a_subsec1' sec,'comp' inv
union all
select 'a_subsec2' sec,'lap' inv
union all
select 'a_subsec2' sec,'comp' inv
union all
select 'a_subsec3' sec,'lap' inv
union all
select 'a_subsec3' sec,'comp' inv
)
select msec,sum(inv_comp) total from(
select concat(substr(sec,1,1),'_sec') as msec,
case when inv='comp' then 1 else 0 end as inv_comp,
tb.*
from tb) z
group by msec
this query might not be the one you want without some modify but main idea is same.
db<>fiddle

Return a Complete sales order where a given item is purchased SQL

I'm trying to query our Sales_Order_Line_Item table. We are introducing a new "Tariff" Item code, our sales staff are required to add this code to all orders that have items that start with "WI". So I need to create a query that will show me any orders that have item codes that start with "WI" but are missing the "Tariff" code.
I can't seem to figure out how to return a list that shows this data.
For simplicity, my Sales_Order_Line_Item Table has these 3 columns:
UNIQUE_LINE_ID, SALE_ORDER_#, ITEM_#
One dirty trick is to use a case expression and count the number of times these items appear:
SELECT sale_order_no
FROM sales_order_line_item
GROUP BY sale_order_no
HAVING COUNT(CASE WHEN item_code LIKE 'WI%' THEN 1 END) > 0 AND
COUNT(CASE WHEN item_code = 'Tarrif' THEN 1 END) = 0
Should be something like this:
select * from Sales_Order_Line_Item
where ItemCode like 'wi%'
and tariff is null
If, you want full order details you can use EXISTS/NOT EXISTS instead :
select so.*
from sales_order_line_item so
where exists (select 1 from sales_order_line_item sol where sol.sale_order_no = s.sale_order_no and sol.item_code LIKE 'WI%') and
not exists (select 1 from sales_order_line_item sol where sol.sale_order_no = s.sale_order_no and sol.item_code = 'Tarrif');

finding specific customers in contract table

I am working with MS SQL and need help creating a query.
I have a table called CustomerContracts, in it is multiple lines per item# for specific customers.
For example real data
item cust_num
x 1156
x 3924
x 7565
x 84339
x 104365
x 106066
x 107377
x 118691
y 1156
y 3924
y 7565
y 84339
y 104365
y 106066
y 107377
So what I need to do is search the table by item number and a specific customer number and return the item if that customer number does not exist as a record for that item.
So, in this case I am checking all item records for the cust_num of 106066 and 118691 if the item does not contain both customers then I want it to be included in my results so in this cause item X would not show up, but item Y would.
I think I need to do some type of count. I have tried using NOT IN(002,003) no luck.
Suggestions?
to satisfy my attempt at this. I have tried at least 8 different ways, this is the latest attempt.
select 'Cust Does not exist' as Status,
i.item as item,
i.description as description,
t.numcusts
From
item i inner join (select count(cust_num) as numcusts,item
from itemcust
where cust_num NOT IN ('106066','118691')
group by item) t on t.item = i.item
where i.stat = 'A' and t.numcusts > 0
order by i.item,i.description
did not work. So, I am still trying to resolve it. I was able to develop a sort of solution using imbedded queries in Access, but can't get the sql it created to port over.
I am guessing that you have multiple records for a customer. You want customers where the table has no record for a given item. One approach is to use group by and having:
select cc.cust_num
from CustomerContracts cc
where c.cust_num in ('001', '002')
group by cc.cust_num
having sum(case when cc.cust_item_num in ('aaa') then 1 else 0 end) = 0;
Another approach is to use not exists:
select cc.*
from CustomerContract cc
where c.cust_num in ('001', '002') and
not exists (select 1 from CustomerContracts where cust_item_num in ('aaa'));
The first gives a list of customer number. The second gives all the records for those customers.
EDIT (based on edit to question):
The question is about items not customers. A modification to the first approach will work. If you only want items that have at least one of the customers, then use a where clause:
select cc.cust_item_num
from CustomerContracts cc
where c.cust_num in (106066, 118691)
group by cc.cust_item_num
having count(distinct c.cust_num) < 2;
If you want all items (even where neither customer appears), then count each customer match separately in the having clause:
select cc.cust_item_num
from CustomerContracts cc
group by cc.cust_item_num
having sum(case when c.cust_num = 106066 then 1 else 0 end) = 0 or
sum(case when c.cust_num = 118691 then 1 else 0 en) = 0;
Thanks for the help, but after 5 cups of coffee and 2 playlists I figured it out
select 'Cust Does not exist' as Status,
i.item as item,
i.description as description,expr1
From
item i RIGHT join (select itemcust.item,
sum(case when LTRIM(RTRIM(cust_num)) = '106066' or LTRIM(RTRIM(cust_num)) ='118691'then 1 else 0 end) as expr1
from itemcust
group by itemcust.item) t on t.item = i.item
where i.stat = 'A' AND expr1 <> 2
order by i.item,i.description
This gives me all the items that do not have both records or actually have them more than once.

select least row per group in SQL

I am trying to select the min price of each condition category. I did some search and wrote the code below. However, it shows null for the selected fields. Any solution?
SELECT Sales.Sale_ID, Sales.Sale_Price, Sales.Condition
FROM Items
LEFT JOIN Sales ON ( Items.Item_ID = Sales.Item_ID
AND Sales.Expires_DateTime > NOW( )
AND Sales.Sale_Price = (
SELECT MIN( s2.Sale_Price )
FROM Sales s2
WHERE Sales.`Condition` = s2.`Condition` ) )
WHERE Items.ISBN =9780077225957
A little more complicated solution, but one that includes your Sale_ID is below.
SELECT TOP 1 Sale_Price, Sale_ID, Condition
FROM Sales
WHERE Sale_Price IN (SELECT MIN(Sale_Price)
FROM Sales
WHERE
Expires_DateTime > NOW()
AND
Item_ID IN
(SELECT Item_ID FROM Items WHERE ISBN = 9780077225957)
GROUP BY Condition )
The 'TOP 1' is there in case more than 1 sale had the same minimum price and you only wanted one returned.
(internal query taken directly from #Michael Ames answer)
If you don't need Sales.Sale_ID, this solution is simpler:
SELECT MIN(Sale_Price), Condition
FROM Sales
WHERE Expires_DateTime > NOW()
AND Item_ID IN
(SELECT Item_ID FROM Items WHERE ISBN = 9780077225957)
GROUP BY Condition
Good luck!