how to check if a type of row exists in a table - sql

Hi I have an order table and a payment table which are linked by order_num. I would like to get entries from order table who have entries in the payment table of PaymentType 'A' as well as PaymentType 'B' and their amounts match. Example order number 411 should only be returned to me if it has at least two payments and one of them is paymenttype 'A' and the other one is paymenttype 'b' and amount for both is 45
Thanks.

Like the comments state, there is very little info to go off of for a truly definitive answer. Here goes a possible solution, at least in a basic form.
SELECT *
FROM Orders o
LEFT JOIN Payment p1 ON o.order_num = p1.order_num
LEFT JOIN Payment p2 ON o.order_num = p2.order_num
WHERE p1.Type = "A"
AND p2.Type = "B"
AND p1.Amount = p2.Amount

As long as you can guarantee that there are at most one A and one B row:
SELECT
<columns here>
FROM
Orders O
INNER JOIN Payments PA ON
PA.order_number = O.order_number AND
PA.payment_type = 'A'
INNER JOIN Payments PB ON
PB.order_number = O.order_number AND
PB.payment_type = 'B'
WHERE
PA.amount = PB.amount

How about this:
SELECT o.OrderID,
o.Amount
FROM Order AS o
INNER JOIN Payment AS pA ON pA.OrderID = o.OrderID AND pA.PaymentType = 'A'
INNER JOIN Payment AS pB ON pB.OrderID = o.OrderID AND pB.PaymentType = 'B'
WHERE pA.Amount = pB.Amount
GROUP BY o.OrderID,
o.Amount

Making some (hopefully) reasonable assumptions about the names of tables, columns, etc, how about...
SELECT *
FROM ORDER_TABLE
WHERE EXISTS (SELECT *
FROM PAYMENT_TABLE
WHERE PAYMENT_TYPE = 'A' AND
PAYMENT_TABLE.ORDER = ORDER_TABLE.ORDER AND
PAYMENT_TABLE.AMOUNT = ORDER_TABLE.AMOUNT) AND
EXISTS (SELECT *
FROM PAYMENT_TABLE
WHERE PAYMENT_TYPE = 'B' AND
PAYMENT_TABLE.ORDER = ORDER_TABLE.ORDER AND
PAYMENT_TABLE.AMOUNT = ORDER_TABLE.AMOUNT);

Assumes amounts exist only in the payment table, and that the payment table may have multiple records for a payment type.
select [columns]
from ORDER O
where exists (select null from PAYMENT PA, PAYMENT PB
where PA.PAYMENT_TYPE = 'A'
and PB.PAYMENT_TYPE = 'B'
and PA.ORDER_NUM = O.ORDER_NUM
and PB.ORDER_NUM = O.ORDER_NUM
and PA.AMOUNT = PB.AMOUNT)

Related

SQL Select Query into another query

I am a beginner with SQL so apologise in advance if my terminology / coding is a little off, or maybe way off.
I have two queries which I would like to join into one. The first creating a list of productids which contain two specific processes.
I then want to use these productids in the second query.
Also is below correct?
group by products.productid having (sum(case when processid like 'pick%' then 1 else 0 end) + sum(case when processid like 'pack%' then 1 else 0 end) = 2)
Any help would be much appreciated, hope this makes sense.
SELECT
Products.ProductID
FROM Products
INNER JOIN Categories ON Products.Category = Categories.Category
INNER JOIN Boms ON Products.Product = Boms.Product AND Boms.BomVersion = Products.BomVersion
LEFT OUTER JOIN Products AS Comp ON Boms.Component = Comp.Product
LEFT OUTER JOIN Processes ON Boms.Process = Processes.Process
WHERE
products.active = 1
and Categorys.Categoryid in ('5','20')
group by products.productid
having (sum(case when processid like 'pick%' then 1 else 0 end) + sum(case when processid like 'pack%' then 1 else 0 end) = 2)
order by products.productid
SELECT
Products.ProductID,
Products.productdescription,
Boms.Type As Type,
Comp.ProductId as Component,
Comp.productdescription,
Boms.Quantity,
BomVersions.BomVersionID,
Processes.processid,
Processes.ProcessDescription
FROM Products
INNER JOIN Categories ON Products.Category = Categories.Category
INNER JOIN Boms ON Products.Product = Boms.Product AND Boms.BomVersion = Products.BomVersion
LEFT OUTER JOIN Products AS Comp ON Boms.Component = Comp.Product
LEFT OUTER JOIN Processes ON Boms.Process = Processes.Process
INNER JOIN BomVersions ON Products.BomVersion = BomVersions.BomVersion
WHERE
products.active = 1
order by products.productid, products.type,comp.productid
To combine them you could do the following.
SELECT b.*
FROM
(SELECT Products.ProductID FROM Products INNER JOIN ...) AS a
INNER JOIN
(SELECT Products.ProductID, Products.productdescription, Boms.Type As Type, ...) AS b
ON a.ProductID = b.ProductID

Need help understanding SUM

I would like to see the results total the received column and only return the item id once with the total received. Can someone explain why this is not working and help me get to where I need to be?
EDIT - Id like the results to be
Item A - 65
Item B - 52
Item C - 150
instead of what I am getting currently:
Item A - 15
Item A - 20
Item A - 30
Item B - 10
Item B - 15
etc
THANKS!
select S.supplier_id,
s.supplier_name,
ph.po_no,
ph.order_date,
ph.location_id,
im.item_id,
im.item_desc,
invs.supplier_part_no,
sum( pl.qty_received) as received,
pl.unit_price
from po_line pl
inner join po_hdr ph on ph.po_no = pl.po_no
inner join supplier s on s.supplier_id = ph.supplier_id
inner join inv_mast im on im.inv_mast_uid = pl.inv_mast_uid
left join inventory_supplier invs on invs.supplier_id = s.supplier_id
and invs.inv_mast_uid = im.inv_mast_uid
where ph.order_date between '2014-01-01' and '2014-12-31'
and ph.supplier_id = '101315'
and ph.delete_flag != 'Y'
and ph.complete = 'y'
and pl.delete_flag != 'y'
and pl.cancel_flag != 'y'
and ph.cancel_flag != 'y'
Group by
pl.qty_received,
im.item_id,
S.supplier_id,
s.supplier_name,
ph.po_no,
ph.location_id,
im.item_desc,
invs.supplier_part_no,
pl.unit_price,
ph.order_date
order by item_id
The problem is that the aggregate is grouping on other, changing values that cause separation in your data.
select S.supplier_id, -- values are the same, but is this necessary in your result set; if this value changes, you would have the separation in your data
s.supplier_name, -- cannot see in your picture, but these are likely all the same
ph.po_no, -- values are different, is this necessary in your result set?
ph.order_date, -- values are different, again, is this necessary in your result set?
ph.location_id, -- values are the same, but is this necessary in your result set; if this value changes, you would have the separation in your data
im.item_id, -- the primary grouping factor
im.item_desc, -- the description of the primary grouping factor (should not change per record)
invs.supplier_part_no, -- values are the same, but is this necessary in your result set; if this value changes, you would have the separation in your data
sum( pl.qty_received) as received, -- the aggregate you are performing
pl.unit_price -- we cannot see this in your picture, but this could also be a changing value that could cause separation in your data, is it necessary in your result set?
from po_line pl
inner join po_hdr ph on ph.po_no = pl.po_no
inner join supplier s on s.supplier_id = ph.supplier_id
inner join inv_mast im on im.inv_mast_uid = pl.inv_mast_uid
left join inventory_supplier invs on invs.supplier_id = s.supplier_id
and invs.inv_mast_uid = im.inv_mast_uid
where ph.order_date between '2014-01-01' and '2014-12-31'
and ph.supplier_id = '101315'
and ph.delete_flag != 'Y'
and ph.complete = 'y'
and pl.delete_flag != 'y'
and pl.cancel_flag != 'y'
and ph.cancel_flag != 'y'
Group by -- the Group by clause should change with a change in the columns selected
pl.qty_received, -- the aggregate should also, likely, not be part of the group by clause
im.item_id,
S.supplier_id,
s.supplier_name,
ph.po_no,
ph.location_id,
im.item_desc,
invs.supplier_part_no,
pl.unit_price,
ph.order_date
order by item_id
-- an example of how this might look
select S.supplier_id,
MAX(s.supplier_name),
im.item_id,
MAX(im.item_desc),
sum( pl.qty_received) as received,
from po_line pl
inner join po_hdr ph on ph.po_no = pl.po_no
inner join supplier s on s.supplier_id = ph.supplier_id
inner join inv_mast im on im.inv_mast_uid = pl.inv_mast_uid
left join inventory_supplier invs on invs.supplier_id = s.supplier_id
and invs.inv_mast_uid = im.inv_mast_uid
where ph.order_date between '2014-01-01' and '2014-12-31'
and ph.supplier_id = '101315'
and ph.delete_flag != 'Y'
and ph.complete = 'y'
and pl.delete_flag != 'y'
and pl.cancel_flag != 'y'
and ph.cancel_flag != 'y'
Group by
S.supplier_id,
im.item_id
order by item_id

A column in the predicate of the SQL

How can I select custType in the predicate section of the query
I can't do so now because
Error code -1, SQL state 42X04: Column 'CUSTTYPE' is either not in any table in the FROM list or appears within a join specification and is outside the scope of the join specification or appears in a HAVING clause and is not in the GROUP BY list. If this is a CREATE or ALTER TABLE statement then 'CUSTTYPE' is not a column in the target table.
select p.SKU AS GiftID, p.ProductName AS GiftName,
case when sa.Sales >= v.LevelUpAmount then 1 else 2 end AS custType
from products p, campaign ca, SubCategory sc,
VIPLevelUpParam v,
ActiveParam a, customer c,
(select c.CustomerCode, sum(od.NetSales) AS Sales from customer c
INNER JOIN orders o ON (c.CustomerCode = o.CustomerCode)
INNER JOIN order_details od ON (o.OrderCode = od.OrderCode)
group by c.CustomerCode ) sa
where ca.CUSTOMERTYPE = custType AND
c.CustomerCode = 'CUS000001-2013-11-06' AND
p.SubCategoryID = sc.SubCategoryCode AND
p.SKU = ca.GiftID AND
sc.SubCategoryName = 'Gift'AND
v.LevelUpID = a.ActiveID AND
a.TableName = 'VIPLevelUpParam'
group by p.SKU, p.ProductName, sa.Sales, v.LevelUpAmount, custType;
Any one shed some light on this, it would be greatly appreciated!
As per logical query processing where clause is evaluated before select statement that why you're getting CustType column won't be available in where clause.
http://blog.sqlauthority.com/2009/04/06/sql-server-logical-query-processing-phases-order-of-statement-execution/
select * from
(
select p.SKU AS GiftID, p.ProductName AS GiftName,
case when sa.Sales >= v.LevelUpAmount then 1 else 2 end AS custType
from products p, campaign ca, SubCategory sc,
VIPLevelUpParam v,
ActiveParam a, customer c,
(select c.CustomerCode, sum(od.NetSales) AS Sales from customer c
INNER JOIN orders o ON (c.CustomerCode = o.CustomerCode)
INNER JOIN order_details od ON (o.OrderCode = od.OrderCode)
group by c.CustomerCode ) sa
) DT
where DT.CUSTOMERTYPE = DT.custType AND
DT.CustomerCode = 'CUS000001-2013-11-06' AND
DT.SubCategoryID = DT.SubCategoryCode AND
DT.SKU = DT.GiftID AND
DT.SubCategoryName = 'Gift' AND
DT.LevelUpID = DT.ActiveID AND
DT.TableName = 'VIPLevelUpParam'
group by DT.SKU, DT.ProductName, DT.Sales, DT.LevelUpAmount, DT.custType;

Issue with performing an aggregate function on an expression containing an aggregate or a subquery

select
A.ACCT as acct, COUNT(TRANS_key) as payments
from
DEBT A
join
TRANS B on B.DEBT_KEY = A.DEBT_KEY
join
TRANS_CODE C on C.TRANS_CODE = B.TRANS_CODE
join
CLIENT D on D.CLIENT_KEY = A.CLIENT_KEY
join
STATUS S on S.STAT_KEY = A. STAT_KEY
where
S.CATEGORY = 'A' and D.CLIENT_KEY = 43
Error:
Cannot perform an aggregate function on an expression containing an
aggregate or a subquery.
I am getting the error above when running this. I am not sure if I should be joining these tables differently or not, but I need this to be working.
All other selects have to be group by. Use this
select A.ACCT as acct, COUNT(TRANS_key) as payments
from DEBT A join TRANS B on B.DEBT_KEY = A.DEBT_KEY
join TRANS_CODE C on C.TRANS_CODE = B.TRANS_CODE
join CLIENT D on D.CLIENT_KEY = A.CLIENT_KEY
join STATUS S on S.STAT_KEY = A. STAT_KEY
where S.CATEGORY = 'A' and D.CLIENT_KEY = 43
GROUP BY A.ACCT
try
select A.ACCT as acct, COUNT(TRANS_key) as payments
from DEBT A
join TRANS B on B.DEBT_KEY = A.DEBT_KEY
join TRANS_CODE C on C.TRANS_CODE = B.TRANS_CODE
join CLIENT D on D.CLIENT_KEY = A.CLIENT_KEY
join STATUS S on S.STAT_KEY = A. STAT_KEY
where S.CATEGORY = 'A' and D.CLIENT_KEY = 43
group by A.ACCT
You can't use a aggregate function like count that return just 1 result and a select that returns multiple. If you want to the count for every a.acct then do the above.

How could I combine these 3 T-SQL statements into one?

I have 3 queries that I want to combine. 1 query is for total sales, 1 is for canceled orders, and 1 is for orders that don't include specific product types. Just need the total sales $$ to output in a table format as they are now. The only thing that changes between the 3 is the where statement. Thanks!
Edit: I realize I said "Just need the total sales $$" ... what I meant was I just need the sales $$ for each query in one table. So $x, $y, $z ... x is the total sales, y is the sales dollars that got cancelled, and z is the sales dollars for the specific items.
SELECT Sum((Items.Total+Items.Shipping)*OrderDetails.Quantity) AS Total
FROM Promo INNER JOIN (Orders INNER JOIN (Items INNER JOIN OrderDetails ON Items.ItemCode = OrderDetails.ItemCode) ON Orders.OrderNumber = OrderDetails.OrderNumber) ON Promo.Promo = Orders.Promo
WHERE ((Promo.OfferType)='Sale') AND ((Items.Date) Between '6/1/2010' And '12/31/2011');
SELECT Sum((Items.Total+Items.Shipping)*OrderDetails.Quantity) AS Canceled
FROM Promo INNER JOIN (Orders INNER JOIN (Items INNER JOIN OrderDetails ON Items.ItemCode = OrderDetails.ItemCode) ON Orders.OrderNumber = OrderDetails.OrderNumber) ON Promo.Promo = Orders.Promo
WHERE (((Promo.OfferType)='Sale') AND ((Items.Date) Between '6/1/2010' And '12/31/2011') AND ((Items.Status)="Canceled"));
SELECT Sum((Items.Total+Items.Shipping)*OrderDetails.Quantity) AS BadItems
FROM Promo INNER JOIN (Orders INNER JOIN (Items INNER JOIN OrderDetails ON Items.ItemCode = OrderDetails.ItemCode) ON Orders.OrderNumber = OrderDetails.OrderNumber) ON Promo.Promo = Orders.Promo
WHERE (((Promo.OfferType)='Sale') AND ((Items.Date) Between '6/1/2010' And '12/31/2011') AND ((Items.ProductType)<>2) AND ((Items.ProductType)<>6));
Thanks!
If you want the results on 1 row:
SELECT Total, Canceled, BadItems
FROM Query1, Query2, Query3
And if you want the results in 1 column, use a UNION:
Query1
UNION
Query2
UNION
Query3
Updated to reflect question clarification:
SELECT Sum(CASE WHEN Items.Status <> 'Canceled' AND Items.ProductType = 4 THEN (Items.Total+Items.Shipping)*OrderDetails.Quantity ELSE 0 END) AS Total ,
Sum(CASE WHEN Items.Status = 'Canceled' AND Items.ProductType = 4 THEN (Items.Total+Items.Shipping)*OrderDetails.Quantity ELSE 0 END) AS Canceled,
Sum(CASE WHEN Items.ProductType <> 4 THEN (Items.Total+Items.Shipping)*OrderDetails.Quantity ELSE 0 END) AS BadItems,
FROM Promo INNER JOIN (Orders INNER JOIN (Items INNER JOIN OrderDetails ON Items.ItemCode = OrderDetails.ItemCode) ON Orders.OrderNumber = OrderDetails.OrderNumber) ON Promo.Promo = Orders.Promo
WHERE ((Promo.OfferType)='Sale') AND ((Items.Date) Between '9/1/2010' And '12/31/2010');
try to use a procedure which will accept three values as input which will suite your were statements and it will give results in one table as want. if you are stuck let me know , i will help.