Splitting table by column value - sql

I have 4 tables I want to join to display items sold and items returned. The issue I'm having is that the sold and returned items are in the same table and I'm having trouble returning a 0 for the 'Return' column when an item is sold without returns and a 0 for the 'Sold' column when an item is returned without a sale. Here's what I'm trying to do,
Locations
LocationID LocationName
1 NY
2 LA
3 Chicago
Items
ItemID ItemName
A Sandwich
B Salad
C Wrap
Deliveries
DeliveryID LocationID
1 1
2 2
3 3
4 1
DeliveryRecords
RecordID DeliveryID ItemID Quantity RecordType
1 1 A 3 SOLD
2 1 B 4 SOLD
3 1 C 5 SOLD
4 1 C 2 RETURN
5 2 A 3 SOLD
6 2 B 2 SOLD
7 3 B 2 SOLD
8 3 C 3 SOLD
9 4 A 1 RETURN
And I want my query to return,
Location DeliveryID Item Sold Returned
NY 1 Sandwich 3 0
NY 1 Salad 4 0
NY 1 Wrap 5 2
LA 2 Sandwich 3 0
LA 2 Salad 2 0
Chicago 3 Salad 2 0
Chicago 3 Wrap 3 0
NY 4 Wrap 0 1

I think you just want conditional aggregation (after a bunch of joins):
select l.locationname, dr.deliveryid, i.itemname,
sum(case when dr.recordtype = 'SOLD' then quantity else 0 end) as sold,
sum(case when dr.recordtype = 'RETURN' then quantity else 0 end) as returned
from deliveryrecords dr join
deliveries d
on dr.deliveryid = d.deliveryid join
location l
on d.locationid = l.locationid join
items i
on dr.itemid = i.itemid
group by l.locationname, dr.deliveridy, i.itemname;

Using JOIN and SUM:
SQL Fiddle
SELECT
l.LocationName,
dr.DeliveryID,
i.ItemName,
[Sold] = SUM(CASE WHEN dr.RecordType = 'SOLD' THEN dr.Quantity ELSE 0 END),
[Returned] = SUM(CASE WHEN dr.RecordType = 'RETURN' THEN dr.Quantity ELSE 0 END)
FROM DeliveryRecords dr
INNER JOIN Items i
ON i.ItemID = dr.ItemId
INNER JOIN Deliveries d
ON d.DeliveryID = dr.DeliveryID
INNER JOIN Locatins l
ON l.LocationID = d.LocationId
GROUP BY
dr.DeliveryID, l.LocationName, i.ItemName

Related

SQL get SUM, COUNT, max, min and names of invoice

I have the following tables:
invoice
id
customerId
date
1
3
2020-10-10
2
NULL
2020-09-10
3
1
2020-10-15
product
id
name
price
1
car
10
2
pen
5
3
laptop
6
4
table
2
customer
id
name
1
a
2
b
3
c
4
d
invoceProduct
id
invoiceid
productid
1
1
1
3
1
2
4
1
4
5
2
2
6
2
3
I need to get the following for each invoice:
invoiceID, date, customerName, Total, Quantity(count of items), max product name and price, min product name and price in each invoice.
I wrote query and get most of values but I cannot get the name of products.
This is my sql query
WITH cte_Products(InvoiceId, date, CustomerName, ProductName, price) AS
(
select
i.id as InvoiceId,
i.date as date,
CASE
when c.name IS NULL THEN 'NoName'
Else c.name
End AS CustomerName,
p.name as ProductName,
p.price as price
from invoceProduct ip
join product p on p.id = ip.productID
join invoice i on i.id = ip.invoiceId
left join customer c on i.customerId = c.id
)
select
cte.InvoiceId,
cte.date,
cte.CustomerName,
SUM(cte.price) as Total,
count(*) AS ItemsQuantity,
MAX(cte.price) AS MostExpensiveItem,
MIN(cte.price) AS CheapestItem
from
cte_Products cte
group by cte.InvoiceId, cte.date, cte.CustomerName;
I got this result
InvoiceId
date
CustomerName
Total
ItemsQuantity
MostExpensiveItem
CheapestItem
1
2020-10-10
c
17
3
10
2
2
2020-09-10
NoName
11
2
6
5
I need to add the product name with product price under MostExpensiveItem and CheapestItem.

join with lookup and group by

i have 2 tables like below:
lk_premier:
code descr
P Premier
N Non Premier
Case:
id taxPin
1 123
2 789
Status:
id voting_status premier
1 5 P
1 5 P
1 5 P
2 5 P
2 5 N
2 5 null
3 5 null
3 5 null
3 5 null
3 5 null
3 5 null
I used the below sql
select
decode(premier,
'P',
'PREMIER',
'N',
'NON PREMIER') as caseStatus,
count(*) as count
from
status s,
case c
where
c.id = s.id
and c.id = 1
and s.voting_status = 5
group by
premier
I want to join the lk_premier table, so my output looks like for id=2,
caseStatus count
PREMIER 1
NON PREMIER 1
for id = 3
caseStatus count
PREMIER 0
NON PREMIER 0
You should never do joins this way -- this way of doing joins was depreciated about 20 years ago. the join should look like this:
join status s on c.id = s.id
once you do joins the right way then how you do left joins is easier as seen below:
here you go
select
coalesce(p.desc,'unknown') as caseStatus,
count(*) as count
from case c
join status s on c.id = s.id
left join lk_premier p on p.code = c.premier
where c.id = 1 and s.voting_status = 5
group by coalesce(p.desc,'unknown')

SQL Self Join to work out freight percentage when invoices are stored in the same table

I need to work out the freight percentage value on each shipment the company brings in. The invoices for the freight and the goods are stored in the same table, VSI denotes a goods invoice, VBL denotes a freight invoice, they are joined together via a job cost. I have tried to self join the sets of tables, but the end sum is always multiplied by the amount of matching records. Any help would be appreciated.
Tables
JobCost
JobCostID JobCostDescription JobCostNumber
4910 ITS-1005104 JBC-1004880
4911 ITS-1005105 JBC-1004881
PurchaseInvoice
PIID PINumber ExchangeRate VendorId
1 VSI-1 1 1
2 VSI-2 1 2
3 VBL-1 1 3
PurchaseInvoiceItem
PIItemID PIID Item
1 1 ProductA
2 1 ProductB
3 2 ProductA
4 2 ProductB
5 3 Fuel
6 3 Handling
PurchaseInvoiceItemDetail
PIItemDetailID QtyShipped Cost PIItemID JobCostID
1 2 2500 1 4910
2 2 2500 2 4910
3 2 2500 3 4911
4 2 2500 4 4911
5 1 25 5 4910
6 1 75 6 4910
Vendor
VendorId VendorCode VendorName
1 VEN1 Vendor1
2 VEN2 Vendor2
3 Freight1 Agent1
Desired result
JobCostID JobCostDescription VendorCode VendorName FreightAgentCode FreightAgentName InvoiceTotal FreightTotal FreightPercentage
4910 ITS-1005104 VEN1 Vendor1 Freight1 Agent1 10000 100 1%
4920 ITS-1005105 VEN2 Vendor2 10000
SELECT tblJobCost1.JobCostID, tblJobCost1.JobCostDescription, tblVendor1.VendorCode, tblVendor1.VendorName, tblVendor2.VendorCode AS 'FreightAgentCode', tblVendor2.VendorName AS 'FreightAgentName',
SUM(PurchaseInvoiceItemDetail1.QtyShipped*PurchaseInvoiceItemDetail1.Cost*PurchaseInvoice1.ExchangeRate) AS 'InvoiceTotal',
SUM(PurchaseInvoiceItemDetail2.QtyShipped*PurchaseInvoiceItemDetail2.Cost*PurchaseInvoice2.ExchangeRate) AS 'FreightTotal',
SUM(PurchaseInvoiceItemDetail2.QtyShipped*PurchaseInvoiceItemDetail2.Cost*PurchaseInvoice2.ExchangeRate)/SUM(PurchaseInvoiceItemDetail1.QtyShipped*PurchaseInvoiceItemDetail1.Cost*PurchaseInvoice1.ExchangeRate)*100 AS 'FreightPercentage'
FROM tblJobCost AS tblJobCost1
LEFT JOIN tblJobCost AS tblJobCost2 ON tblJobCost1.JobCostID = tblJobCost2.JobCostID
LEFT JOIN tblPurchaseInvoiceItemDetail AS tblPurchaseInvoiceItemDetail1 ON tblJobCost1.JobCostID = tblPurchaseInvoiceItemDetail1.JobCostID
LEFT JOIN tblPurchaseInvoiceItemDetail AS tblPurchaseInvoiceItemDetail2 ON tblJobCost2.JobCostID = tblPurchaseInvoiceItemDetail2.JobCostID
LEFT JOIN tblPurchaseInvoiceItem AS tblPurchaseInvoiceItem1 ON tblPurchaseInvoiceItem1.PIItemID = tblPurchaseInvoiceItemDetail1.PIItemID
LEFT JOIN tblPurchaseInvoiceItem AS tblPurchaseInvoiceItem2 ON tblPurchaseInvoiceItem2.PIItemID = tblPurchaseInvoiceItemDetail2.PIItemID
LEFT JOIN tblPurchaseInvoice AS tblPurchaseInvoice1 ON tblPurchaseInvoiceItem1.PIID = tblPurchaseInvoice1.PIID
LEFT JOIN tblPurchaseInvoice AS tblPurchaseInvoice2 ON tblPurchaseInvoiceItem2.PIID = tblPurchaseInvoice2.PIID
LEFT JOIN tblVendor AS tblVendor1 ON tblVendor1.VendorId = tblPurchaseInvoice1.VendorID
LEFT JOIN tblVendor AS tblVendor2 ON tblVendor2.VendorId = tblPurchaseInvoice2.VendorID
WHERE tblPurchaseInvoice1.PINumber LIKE 'VSI%' AND tblPurchaseInvoice2.PINumber LIKE 'VBL%'
GROUP BY tblJobCost1.JobCostID, tblJobCost1.JobCostDescription, tblVendor1.VendorCode, tblVendor1.VendorName, tblVendor2.VendorCode, tblVendor2.VendorName
Then you are missing a critical condition:
...
LEFT JOIN tblPurchaseInvoiceItemDetail AS tblPurchaseInvoiceItemDetail2
ON tblJobCost2.JobCostID = tblPurchaseInvoiceItemDetail2.JobCostID
AND tblPurchaseInvoiceItemDetail1.JobCostID = tblPurchaseInvoiceItemDetail2.JobCostID
...

How to show all products which not included in another table. by STRING_AGG

I am currently working on part of a project which is about products and variants.
Product Table
productID productName
-------------------------
1 Perfume X
2 Perfume Y
Variants Table
variantID variantName productID
1 color 1
2 volume 1
VariantValue Table
variantValueID variantValue variantID
1 Red 1
2 Blue 1
3 Green 1
4 100ML 2
5 50ML 2
ProductVariant Table
productVariantID productID sku price
1 1 111 50.00
2 1 222 30.00
4 1 333 15.00
5 2 444 10.95
ProductDetail Table
ProductDetailID productVariantID variantValueID
1 1 1
2 1 4
3 2 1
4 2 5
5 4 2
6 4 5
relationship
and when I call this query ..
SELECT p.productName + ' ' + STRING_AGG(vv.variantValue,' ') product,pv.price
FROM
product p
JOIN ProductVariant pv ON pv.productID = p.productID
JOIN ProductDetail pd ON pv.productVariantID = pd.productVariantID
join VariantValue vv ON pd.variantValueID = vv.variantValueID
GROUP BY pd.productVariantID, p.productName,pv.price
I get the following result ..
product price
Perfume X Red 100ML 50.00
Perfume X Red 50ML 30.00
Perfume X Blue 50ML 15.00
So far so good, it shows all products with the prices but when I insert a new product without variants (simple product) it does not appeared. In my case Perfume Y does not have any variants.
I tried using right and full join but in vain. How I show all products including those product that have no variants.
I think you just want a left join:
SELECT p.productName + COALESCE(' ' + STRING_AGG(vv.variantValue,' '), '') as product,
pv.price
FROM product p LEFT JOIN
ProductVariant pv
ON pv.productID = p.productID LEFT JOIN
ProductDetail pd
ON pv.productVariantID = pd.productVariantID LEFT JOIN
VariantValue vv
ON pd.variantValueID = vv.variantValueID
GROUP BY p.productName, pv.price

Avoid repeatation of rows for every instance when joined with a table

Hi i have 3 tables and i am trying to join them to get a desire table. I have tried group by and temp tables options to get the desired table but no help. I want to avoid duplicates for every instance of a value in one table from another table.
Table 1 Customer Table:
CstId CstDetails CstType
---------- --------------- ------------
1 address 1 1
2 address 2 1
3 address 3 1
4 address 4 2
5 address 5 2
Table 2 Customer Relationship:
CstId CstGroupId
---------- ----------------
1 4 (this is same as CustomerId)
2 5 (this is same as CustomerId)
3 4 (this is same as CustomerId)
Table 3 Customer Notes:
CstId NotesId NoteTxt
----------- --------- ---------
1 1 note11
1 2 note12
1 3 note13
3 1 note31
4 1 note41
4 2 note42
4 3 note43
4 4 note44
4 5 note45
Now i want the result to be in the below format
Table result:
(NoteId) (Notetxt) (NoteId) (Notetxt)
CstId CstDetails CstGroupId CstNoteId CstNote CstGroupNoteId CstGroupNote
1 address1 4 1 note11 1 note41
1 address1 4 2 note12 2 note42
1 address1 4 3 note13 3 note43
1 address1 4 null null 4 note44
1 address1 4 null null 5 note45
But i am getting CstGroupNote repeated for all the CstNote, which i am trying to avoid.
Is there a way i could achieve this result?
Below is the code i use:
select c.cstid, c.cstdetails, cn.cstnotesid, cn.cstnotetxt
insert into temp1
from customer c
left outer join customernotes cn
on c.cstid = cn.cstid
where c.customertypeid = 1
select cr.cstid, cr.cstgroupid, cn.cstgroupnoteid, cn.cstnotetxt
insert into temp2
from customerrelationship cr
left outer join customernotes cn
on cr.cstgroupid = cn.customerid
select t1.cstid, t1.cstdetails, t1.cstnotesid, t1.cstnotetxt, t2.cstgroupnoteid, t2.cstnotetext
from temp1 t1
left outer join t2
on t1.cstid = t2.cstid
Try:
select CstId,
max(CstDetails) CstDetails,
max(CstGroupId) CstGroupId,
max(CstNoteId) CstNoteId,
max(CstNote) CstNote,
max(CstGroupNoteId) CstGroupNoteId,
max(CstGroupNote) CstGroupNote
from
(select c.CstId,
c.CstDetails,
0 CstGroupId,
n.NotesId CmbNotesId,
n.NotesId CstNoteId,
n.NoteTxt CstNote,
0 CstGroupNoteId,
'' CstGroupNote
from customer c
left outer join customernotes n on c.cstid = n.cstid
where c.customertypeid = 1
union all
select c.CstId,
c.CstDetails,
r.CstGroupId,
n.NotesId CmbNotesId,
0 CstNoteId,
'' CstNote,
n.NotesId CstGroupNoteId,
n.NoteTxt CstGroupNote
from customer c
left outer join customerrelationship r on c.cstid = r.cstid
left outer join customernotes n on r.CstGroupId = n.cstid
where c.customertypeid = 1) u
group by CstId, CmbNotesId
Use a derived table and an outer join
The trick there is the
and cn.cstnotesid = cG.cstnotesid
to link those two on one row
select c.cstid, c.cstdetails, cn.cstnotesid, cn.cstnotetxt
,cG.CstGroupId, cG.cstnotesid, cG.cstnotetxt
from customer c
join customernotes cn
on cn.cstid = c.cstid
outer join (select c.cstid, c.CstGroupId, cn.cstnotesid, cn.cstnotetxt
from customer c
join customernotes cn
on cn.cstid = c.CstGroupId) as cG
on c.cstid = cG.cstid
and cn.cstnotesid = cG.cstnotesid
order by c.cstid, cn.cstnotesid, cG.cstnotesid