Create SQL statement with mulitple AND - sql

I have a problem with creating right SQL request.
This is my table:
item warehouse amount
item1 A 1
item1 B 5
item2 A 9
item2 B 2
item3 A 1
item3 A 0
item4 B 1
I would like to display all items that:
-Are in warehouse A in number less than 2
-Are in watehouse B in number grater than 0
At the same time.
I would expect item1 will be displayed.
My code so far is:
SELECT item, warehouse , amount
FROM XXXX
WHERE
(warehouse = B AND amount>0)
AND
(warehouse = A AND amount<2)
I know that warehouse = B AND warehouse = A will never happened, but i do not have any idea where to go from here.
I'am new to SQL, but i have feeling that i need to use GRUPBY
Any help ?

You can use aggregation. Use where to get either condition. Then check that both are met. Assuming that there is one row per item per warehouse, you can use:
SELECT item
FROM XXXX
WHERE (warehouse = 'B' AND amount > 0) OR
(warehouse = 'A' AND amount < 2)
GROUP BY item
HAVING COUNT(*) = 2;
Note that this does not return the amounts. If you want that as well, then pivot the data using conditional aggregation:
SELECT item,
SUM(CASE WHEN warehouse = 'B' THEN amount END) as b_amount,
SUM(CASE WHEN warehouse = 'A' THEN amount END) as a_amount
FROM XXXX
WHERE (warehouse = 'B' AND amount > 0) OR
(warehouse = 'A' AND amount < 2)
GROUP BY item
HAVING COUNT(*) = 2;

Related

What does a multiple count query in SQL return?

I have a product table and every product might be delivered, idle, shipping, preparing.
I want to show a list with the counts of products for each state, and I can see how to query for that here:
How to get multiple counts with one SQL query?
However, what does this query return, and how do I assign the return value to lets say, 4 integers, called deliveredCount, idleCount, shippingCount, preparingCount?
PS: For the record, I am using SQLite with OrmLite in Android with JAVA
EDIT: In this SO question people explain what Query to do when you want to get multiple counts, but they don't tell us what does that query return and in what format. For example:
SELECT a.distributor_id,
(SELECT COUNT(*) FROM myTable WHERE level='personal' and distributor_id = a.distributor_id) as PersonalCount,
(SELECT COUNT(*) FROM myTable WHERE level='exec' and distributor_id = a.distributor_id) as ExecCount,
(SELECT COUNT(*) FROM myTable WHERE distributor_id = a.distributor_id) as TotalCount
FROM myTable a ;
What is the return type of this and what is the format?
PS2: Someone was really quick to downvote my question because it lacked sufficient information. Then I edited it, but the downvote still remains :(
Hard to say for sure but sounds like you need to use a version of the top answer in the link you have provided.
Something like;
SELECT ProductID,
COUNT(*) AS Total,
SUM(CASE WHEN pStatus = 'delivered' THEN 1 ELSE 0 END) DeliveredCount,
SUM(CASE WHEN pStatus = 'idle' THEN 1 ELSE 0 END) IdleCount,
SUM(CASE WHEN pStatus = 'shipping' THEN 1 ELSE 0 END) ShippingCount,
SUM(CASE WHEN pStatus = 'preparing' THEN 1 ELSE 0 END) PreparingCount
FROM ProductTable
GROUP BY ProductID
This will return something like;
ProductID | DeliveredCount | IdleCount | ...
1 | 250 | 3250 | ...
You might want to try this.
SELECT
SUM(CASE WHEN Prod = 'delivered' THEN 1 ELSE 0 END) as deliveredCount,
SUM(CASE WHEN Prod = 'idle' THEN 1 ELSE 0 END) as idleCount,
SUM(CASE WHEN Prod = 'shipping' THEN 1 ELSE 0 END) as shippingCount,
SUM(CASE WHEN Prod = 'preparing' THEN 1 ELSE 0 END) as preparingCount
FROM Product
select
concat(state, "Count"),
count(*)
from product
group by state
Which would return 4 rows (assuming four unique values of state):
fooCount | 15
etc

sql not in and in oporators

HI I am unable to filter materials that belong to only specific list.
Select material
from price
where region='04'
and pricelist ='5'
and pricelist not in ('4','6','7');
I want only those materials which are unique only in pricelist 5 and not in any other pricelists. how can i get this?
You might try something like this (alternately, you could do a self-join, but I think this is just as easy, if not easier, to understand):
SELECT material
FROM price a
WHERE region = '04'
AND pricelist = '5'
AND NOT EXISTS ( SELECT 1 FROM price b
WHERE b.material = a.material
AND b.region = a.region
AND b.pricelist != a.pricelist )
What the above will do will find values of material in region '04' where the pricelist is '5' while excluding those same materials in the same region but on a different price list.
Your current query will only return results where pricelist = 5 -- the not in statement is irrelevant unless it exclude that record. It sounds like you want to return any material which matches on the 5, but doesn't have any other non-5 matches.
One option is to use exist. Here's another option using conditional aggregation with max and case which eliminates the need for multiple queries:
select material
from (
select material,
max(case when pricelist = '5' then 1 else 0 end) haspl5,
max(case when pricelist != '5' then 1 else 0 end) hasothers
from price
where region='04'
group by material
) t
where haspl5 = 1 and hasothers != 1
SQL Fiddle Demo

SQL Count with multiple conditions then join

Quick one,
I have a table, with the following structure
id lid taken
1 1 0
1 1 0
1 1 1
1 1 1
1 2 1
Pretty simply so far right?
I need to query the taken/available from the lid of 1, which should return
taken available
2 2
I know I can simply do two counts and join them, but is there a more proficient way of doing this rather than two separate queries?
I was looking at the following type of format, but I can not for the life of me get it executed in SQL...
SELECT
COUNT(case taken=1) AS taken,
COUNT(case taken=0) AS available FROM table
WHERE
lid=1
Thank you SO much.
You can do this:
SELECT taken, COUNT(*) AS count
FROM table
WHERE lid = 1
GROUP BY taken
This will return two rows:
taken count
0 2
1 2
Each count corresponds to how many times that particular taken value was seen.
Your query is correct just needs juggling a bit:
SELECT
SUM(case taken WHEN 1 THEN 1 ELSE 0 END) AS taken,
SUM(case taken WHEN 1 THEN 0 ELSE 1 END) AS available FROM table
WHERE
lid=1
Alternatively you could do:
SELECT
SUM(taken) AS taken,
COUNT(id) - SUM(taken) AS available
FROM table
WHERE
lid=1
SELECT
SUM(case WHEN taken=1 THEN 1 ELSE 0 END) AS taken,
SUM(case WHEN taken=0 THEN 1 ELSE 0 END) AS available
FROM table
WHERE lid=1
Weird application of CTE's:
WITH lid AS (
SELECT DISTINCT lid FROM taken
)
, tak AS (
SELECT lid,taken , COUNT(*) AS cnt
FROM taken t0
GROUP BY lid,taken
)
SELECT l.lid
, COALESCE(a0.cnt, 0) AS available
, COALESCE(a1.cnt, 0) AS taken
FROM lid l
LEFT JOIN tak a0 ON a0.lid=l.lid AND a0.taken = 0
LEFT JOIN tak a1 ON a1.lid=l.lid AND a1.taken = 1
WHERE l.lid=1
;

SQL Pivot on subset

I have the following result set:
Type | Method | Amount
Type1 Cash Amount
Type1 Check Amount
Type2 Cash Amount
Type2 Check Amount
Type3 Cash Amount
Type3 Check Amount
And I want to make it look like this:
Type | Cash | Check
Type1 Amount Amount
Type2 Amount Amount
Type3 Amount Amount
How can I achieve this in T-SQL (2005 syntax ok)? I need to pivot by type (1, 2, 3...)
Here's an attempt at PIVOT:
select *
from YourTable
PIVOT (sum(amount) FOR Method in (Cash,Check)) as Y
Given that it's just two columns, could try with a join:
select
type
, cash = a.amount
, check = b.amount
from yourtable a
full join yourtable b on a.type = b.type
where a.method = 'cash' or b.method = 'Check'
Or better yet:
select
Type
, Cash = sum(case when Method = 'Cash' then Amount end)
, Check = sum(case when Method = 'Check' then Amount end)
from yourtable
group by
Type
Add an ELSE 0 to the CASE statements if appropriate.
This form is more flexible than the PIVOT operator and doesn't require a FULL JOIN. Just straight aggregation.

SQL - Count( ) issue

I have a table with a charge/credit column:
Item | PriceVal | CostVal | CHARGE_CODE
1 5 3 CH
2 8 5 CH
1 -5 -3 CR
3 7 1 CH
4 15 10 CH
1 5 3 CH
I've got the query I need to get the NET price and cost, but I'm also interested in the NET charges. Right now I have:
SELECT Item, SUM(PriceVal), SUM(CostVal)
FROM Table
GROUP BY Item
How do I get another column with the value
COUNT(SUM(CHARGE_CODE=CH)-SUM(CHARGE_CODE=CR))
I'm at a loss.
count() is going to count one for every value thats not null, so I don't think thats exactly what you want. Take the count out and just take the
sum(case when charge_code = CH then costval else 0 end)
- sum(case when charge_code = 'CR' then costval else 0 end)
Since you have the dollar values entered as negatives in the table already, you can use the simple formula:
select
Item,
sum(PriceVal),
sum(CostVal),
sum(PriceVal-CostVal)
from Table
group by Item
I don't believe you should be subtracting the credit items as they're already negative.
If you really do want want the net count of transactions:
select
Item,
sum(PriceVal),
sum(CostVal),
sum(case when charge_code = 'CH' then 1 else 0 end) -
sum(case when charge_code = 'CR' then -1 else 0 end)
from Table
group by Item
or, if there are only two charge codes, substitute:
sum(case when charge_code = 'CH' then 1 else -1 end)
for the last column.
Not 100% sure what you want, but you can count only certain rows like this:
SELECT COUNT(IF(CHARGE_CODE=CH,1,NULL)) ...
And similarly sum certain values from certain rows like this:
SELECT SUM(IF(CHARGE_CODE=CH,PriceVal,0)) ...