Zero Fill Data for Missing Dates - sql

I have two tables:
Cust Sales Week
123 4 1/8/2015
123 3 1/22/2015
234 4 1/1/2015
.
Week
1/1/2015
1/8/2015
1/15/2015
1/22/2015
I want to combine them so that every Cust has every date and where there are no Sales it is filled with 0.
Cust Sales Week
123 4 1/1/2015
123 0 1/8/2015
123 0 1/15/2015
123 3 1/22/2015
234 4 1/1/2015
234 0 1/8/2015
234 0 1/15/2015
234 0 1/22/2015
Is there a way I can 'select distinct(Cust)' and join them somehow?

First, generate the rows you want using a cross join. Then bring in the data you want using a left join:
select c.cust, w.week, coalesce(t.sales, 0) as sales
from weeks w cross join
(select distinct cust from t) c left join
t
on t.cust = c.cust and t.week = w.week;

You can left join on the dates table and use isnull on the sales column. Use an equivalent of isnull in Netezza.
select t1.cust, isnull(t1.sales,0), t2.week
from daystable2 t2 left join salestable1 t1 on t1.week = t2.week

I think this will do the trick
SELECT week, cust, COALESCE(sales, 0)
FROM week_tbl a LEFT JOIN cust_table b
ON a.week = b.week

Related

SQL join type to have as many rows as each date for each customer

I have these two tables
date
2017-1
2017-2
2017-3
2017-4
2017-5
2017-6
and
date
customer
no_orders
city_code
2017-1
156
1
DNZ
2017-3
156
5
LON
2017-5
156
4
DNZ
2017-6
156
2
YQB
How can I join these two tables to have one row for each customer for all the dates same as below?
If on a date, the customer has no order, its no_order should be 0 and its city_code should be the city_code of the previous date.
date
customer
no_orders
city_code_2
2017-1
156
1
DNZ
2017-2
156
0
DNZ
2017-3
156
5
LON
2017-4
156
0
LON
2017-5
156
4
DNZ
2017-6
156
2
YQB
This code by #Tim Biegeleisen resolved part 1 of my question but now I want to handle both parts with each other.
SELECT d.date, c.customer, COALESCE(t.no_orders, 0) AS no_orders
FROM dates d
CROSS JOIN (SELECT DISTINCT customer FROM customers) c
LEFT JOIN customers t
ON t.date = d.date AND
t.customer = c.customer
ORDER BY c.customer, d.date;
We can use the following calendar table approach:
SELECT d.date, c.customer, COALESCE(t.no_orders, 0) AS no_orders
FROM dates d
CROSS JOIN (SELECT DISTINCT customer FROM customers) c
LEFT JOIN customers t
ON t.date = d.date AND
t.customer = c.customer
ORDER BY c.customer, d.date;
This assumes that the first table is called dates and the second table customers. The query works by using a cross join to generate a set of all dates and customers. We then left join to the second table to bring in the number of orders for a given customer on a given day. Absent number of orders are reported as zero.

SQL get count(*) before several dates

It sounds so simple but I can't figure it out. I have 2 tables:
TABLE 1 contains a list of projects with the dates at which they were approved.
PROJECT
APPROVAL_DATE
A
12/06/2019
A
01/09/2020
A
05/08/2021
A
07/12/2021
B
01/05/2018
B
06/09/2019
B
12/23/2020
TABLE 2 contains dates when tests were performed on these projects.
PROJECT
TEST_DATE
A
01/06/2019
A
01/07/2019
A
02/21/2019
...
...
A
06/22/2021
...
...
B
01/12/2021
...
...
THIS IS WHAT I NEED: For each project, I want to count the total number of tests prior to each APPROVAL_DATE, so I would have this:
PROJECT
APPROVAL_DATE
TOTAL_TESTS_BEFORE_APPROVAL_DATE
A
12/06/2019
1264
A
01/09/2020
1568
A
05/08/2021
1826
A
07/12/2021
2209
B
01/05/2018
560
B
06/09/2019
790
B
12/23/2020
1560
here is how you can do it using left join :
select t1.project, t1.APPROVAL_DATE, count(t2.test_date) TOTAL_TESTS_BEFORE_APPROVAL_DATE
from table1 t1
left join table2 t2
on t1.project = t2.project
and t1.APPROVAL_DATE > t2.TEST_DATE
group by t1.project, t1.APPROVAL_DATE

Subtotal Using Query

I have a table like this:
Date Document No. Item Quantity Price
1/2/2019 1 ADUKU SS 1 1450
1/2/2019 1 AL GUIDE 1 250
1/2/2019 2 AL FLAT 1 75.65
1/2/2019 2 BATTERY(SMALL) 2 7.52
1/2/2019 2 Item 2 2 72.15
1/2/2019 2 Item3 2 58.75
1/6/2019 3 PAPER WHITE 0.25 1250
I need the output as along with subtotal like this:
Date Document No. Item Quantity Price
1/2/2019 1 ADUKU SS 1 1450
1/2/2019 1 AL GUIDE 1 250
1/2/2019 2 AL FLAT 1" 3 MM 1 75.65
1/2/2019 2 BATTERY 2 7.52
1/2/2019 2 Item 2 2 72.15
1/2/2019 2 Item3 2 58.75
1/2/2019 Subtotal 1914.07
1/6/2019 3 PAPER WHITE 0.25 1250
1/6/2019 Subtotal 1250
How to get the desired output like this using sql query?
I need to get subtotal based on the date.
What I tried so far is as follows :
SELECT T0.[DocDate] AS 'Date', T1.[DocNum] AS 'Document No', T0.[Dscription] AS 'Item',
T0.[Quantity] AS 'Quantity', T0.[StockPrice] AS 'Inventory Price'
FROM [table_1] T0
INNER JOIN [table_2] T1
ON T1.[DocEntry] = T0.[DocEntry]
UNION ALL
SELECT T1.[DocDate] as 'Date', NULL,NULL,NULL, SUM(T0.StockPrice)
FROM [table_1] T0
INNER JOIN [table_2] T1
ON T1.[DocEntry] = T0.[DocEntry]
GROUP BY T1.[DocDate]
You can use a UNION to your table and the sums:
select *
from documents
union all
select
date,
null documentno,
'Subtotal' item,
null quantity,
sum(price) price
from documents
group by date
order by
date,
case when documentno is null then 1 else 0 end,
documentno
See the demo
The syntax suggests that this is not a MySQL query. Assuming SQL Server (which is consistent with the square braces), uou can use grouping sets, but you need an aggregation query:
SELECT T1.DocDate, T1.DocNum, T2.Dscription AS Item,
SUM(T1.Quantity) AS Quantity,
T1.StockPrice AS InventoryPrice
FROM [table_1] T1 INNER JOIN
[table_2] T2
ON T2.[DocEntry] = T1.[DocEntry]
GROUP BY GROUPING SETS ( (T1.DocDate, T1.DocNum, T2.Dscription), (T1.DocDate, T2.Dscription) );

cross reference nearest date data

I have three table ElecUser, ElecUsage, ElecEmissionFactor
ElecUser:
UserID UserName
1 Main Building
2 Staff Quarter
ElecUsage:
UserID Time Amount
1 1/7/2010 23230
1 8/10/2011 34340
1 8/1/2011 34300
1 2/3/2012 43430
1 4/2/2013 43560
1 3/2/2014 44540
2 3/6/2014 44000
ElecEmissionFactor:
Time CO2Emission
1/1/2010 0.5
1/1/2011 0.55
1/1/2012 0.56
1/1/2013 0.57
And intended outcome:
UserName Time CO2
1 2010 11615
1 2011 37752 (34340*0.55 + 34300*0.55)
1 2012 24320.8
1 2013 24829.2
1 2014 25387.8
2 2014 25080
The logic is ElecUsage.Amount * ElecEmissionFactor.
If same user and same year, add them up for the record of that year.
My query is:
SELECT ElecUser.UserName, Year([ElecUsage].[Time]), SUM((ElecEmissionFactor.CO2Emission*ElecUsage.Amount)) As CO2
FROM ElecEmissionFactor, ElecUser INNER JOIN ElecUsage ON ElecUser.UserID = ElecUsage.UserID
WHERE (((Year([ElecUsage].[Time]))>=Year([ElecEmissionFactor].[Time])))
GROUP BY ElecUser.UserName, Year([ElecUsage].[Time])
HAVING Year([ElecUsage].[Time]) = Max(Year(ElecEmissionFactor.Time));
However, this only shows the year with emission factor.
The challenge is to reference the year without emission factor to the latest year with emission factor.
Sub-query may be one of the solutions but i fail to do so.
I got stuck for a while. Hope to see your reply.
Thanks
Try something like this..
-- not tested
select T1.id, year(T1.time) as Time, sum(T1.amount*T2.co2emission) as CO2
from ElecUsage T1
left outer join ElecEmissionFactor T2 on (year(T1.time) = year(T2.time))
Group by year(T1.time), T1.id
use sub query to get the corresponding factor in this way
select T1.id,
year(T1.time) as Time,
sum(T1.amount*
(
select top 1 CO2Emission from ElecEmissionFactor T2
where year(T2.time) <= year(T1.time) order by T2.time desc
)
) as CO2
from ElecUsage T1
Group by year(T1.time), T1.id

Adding duplicate values in sql

I'm just a newbie in programming and I'm having a problem with this (see table below).
DocNum DocDate Quantity ItemGroupCode ItemGroupName
89226 7-Nov-12 10 103 Fish-Fillet
88768 8-Nov-12 1 104 Fish-Regular
88856 6-Nov-12 2 104 Fish-Regular
88678 20-Nov-12 12 109 Value Added
89415 5-Nov-12 12 109 Value Added
88642 5-Nov-12 1 112 Other Charges
88646 5-Nov-12 20 112 Other Charges
88729 7-Nov-12 5.64 112 Other Charges
88804 12-Nov-12 10 112 Other Charges
88992 12-Nov-12 1 112 Other Charges
I want to combine similar Code of ItemGroupCode column then Add its Quantity.
EX.
Quantity ItemGroupCode ItemGroupName
10 103 Fish-Fillet
3 104 Fish-Regular
24 109 Value Added
38.64 112 Other Charges
Thanks ...
Pipay
Try this:
select sum(quantity) quantity, itemgroupcode, itemgroupname
from table_name
group by itemgroupcode, itemgroupname
For your question if I understand correctly, you need from the select you provide in your comments, to have the output of the first question. If this is the case then try something like this:
SELECT SUM(quantity), ItemGroupCode, ItemClass
FROM
(SELECT A.DocNum, A.DocDate, B.Quantity,B.Price,B.Linetotal, A.Doctotal, C.ItemName, C.ItmsGrpCod as ItemGroupCode,
D.ItmsGrpnam as ItemClass
FROM OINV as A LEFT outer JOIN INV1 As B ON A.DocEntry = B.DocEntry
LEFT OUTER JOIN OITM As C ON B.ItemCode = C.ItemCode
LEFT OUTER JOIN OITB As D ON C.ItmsGrpCod = D.ItmsGrpCod
WHERE A.DocDate >= '11/01/2012'
group by A.DocNum, A.DocDate, B.Quantity,B.Price,B.Linetotal, A.Doctotal, C.ItemName, C.ItmsGrpCod, D.ItmsGrpnam
order by C.ItmsGrpCod ASC) X
GROUP BY X.ItemGroupCode, X.ItemClass