Aggregate from two tables - sql

I have two tables
Table 'Sales Line' (SL)
Date "Entry No" Item Qty
(PK)
01/01/2018 1 ABC 1
01/02/2018 2 ABC 2
03/02/2018 3 DEF 1
04/06/2018 4 DEF 3
01/01/2019 5 DEF 1
06/06/2019 6 ABC 2
Table 'Cost Breakdown' (CB)
"SL Entry No" Cost
(FK)
1 10
1 15
2 5
3 25
4 10
4 10
5 5
6 5
6 10
Expected result:
Item Tot_Qty Tot_Cost
ABC 3 30
DEF 4 45
Note that I'm only interested on transaction in 2018 only.
How do I aggregate Tot_Qty and Tot_Cost ? Thank you
With query suggested by #GMB, the result is :
Item Tot_Qty Tot_Cost
ABC 4 30
DEF 7 45
so, line from SL will be repeated as many as correponding number of lines in CB.

You can join both tables, filter on the date, and aggregate by item:
select sl.item, sum(sl.qty) tot_qty, sum(sl.qty * cb.cost) tot_cost
from sales_line sl
inner join cost_breakdown cb on cb.sl_entry_no = sl.entry_no
where sl.date >= '20180101' and sl.date < '20190101'
group by sl.item

Related

Customers who bought and not bought some product in last 90 days

I need a dax measure which shows me which customers bought products B and C in last 90 days.
And another one which shows me those whose bought products B and C in last 90 days.
(based in my filter date context)
Below is like it should be:
Can someone help me?
Here is a sample data if needed:
FactSales
KeyDate KeyCustomer KeyProduct Total
1 1 1 12,9
1 2 2 13
1 3 1 156,4
1 4 1 564,8
2 1 1 894,8
2 2 1 56,5
3 1 2 564,85
3 2 3 564,8
4 1 1 1325,6
4 2 1 132,3
Customer
KeyCustomer Name
1 Jean
2 Mari
3 Lisa
4 Julian
5 Jhonny
Calendar
KeyDate Date
1 01/01/2018
2 02/01/2018
3 01/05/2018
4 01/08/2018
Product
KeyProduct Product
1 A
2 B
3 C
Try something along these lines:
IfBought = IF(
COUNTROWS(
FILTER(FactSales,
RELATED('Product'[Product]) IN {"B", "C"} &&
RELATED('Calendar'[Date]) > TODAY() - 90)
) > 0,
1, 0)
Note that May 1st is longer than 90 days ago as of today though, so you won't get the result you asked for unless you change 90 to 114 or greater.

How to rewrite query which gives amount of specific value in row to avoid some values and count further with others?

I have a query which gives me amount of grade 5 for every student in row (if student don't have any other grade on the way):
select distinct on (student, class) scg.*
from (select student, class, grade, count(*) as cnt,
min(gradeDate), max(gradeDate), min_gradeDate, max_gradeDate
from (select t.*,
row_number() over (partition by student, class, grade order by gradeDate) as seqnum_scg,
row_number() over (partition by student, class order by gradeDate) as seqnum_sc
from t
) t
where grade = 5
group by student, class, grade, (seqnum_sc - seqnum_scg)
) scg
order by student, class, cnt desc;
The original problem is explained here:
How to count data with specific values and for specific user/person (in row)?
But now I want to extend this query with one more feature. This counter gives me max value unless some student have grade 4/3/2/1, but now I want it to:
stop counting if student has 4 or 3 grade and start over (with previous max) when student get another 5
What I mean:
Actual query: 5, 5, 5, 4, 3, 5, 5, 2 --> gives me max = 3
New query: 5, 5, 5, 4, 3, 5, 5, 2 --> gives me max = 5, because 4 and 3 stop counter and start it when user gets another 5
stop counting if student gets grade 2 or 1 (and give me max value before getting 2/1 grade) So the same thing which query does now for every grade except 5, but I want it only for 2 and lower (that I can specify in query).
Can someone help me rewrite the second query given by #Gordon Linoff to work like that and tell me what changed?
Edit: examples as requested:
id student grade class gradeDate
1 1 5 1 2017-03-03
2 1 5 1 2017-03-04
3 1 1 1 2017-03-05
4 1 5 1 2017-03-06
5 1 5 1 2017-03-07
6 1 5 1 2017-03-08
7 1 1 1 2017-03-09
8 2 5 2 2017-03-03
9 3 5 3 2017-03-03
10 4 5 4 2017-03-03
11 4 5 4 2017-03-04
12 4 4 4 2017-03-05
13 4 3 4 2017-03-06
14 4 5 4 2017-03-07
15 4 5 4 2017-03-08
16 5 5 5 2017-03-01
17 5 5 5 2017-03-03
18 5 5 5 2017-03-04
19 5 5 5 2017-03-05
20 5 5 5 2017-03-06
21 5 2 5 2017-03-07
22 5 5 5 2017-03-08
23 5 5 5 2017-03-09
Student one : max = 3
Student two : max = 1
Student three : max = 1
Student four : max = 4 (grade 4 and 3 stop counter, but don't reset it)
Student five : max = 5 (because grade 2 reset counter, lack of grade on date
2017-03-02 is not a problem for counter)
One of the methods can be using 2 subqueries and one analytic function
Demo: http://sqlfiddle.com/#!15/74b71/10
SELECT student, max( xxx )
FROM (
SELECT student, grp_nbr, count(CASE WHEN grade = 5 THEN 1 END) As xxx
FROM (
SELECT *,
SUM ( CASE WHEN grade in (1,2)
THEN 1 ELSE 0
END
) OVER (Partition by student Order By gradeDate ) As grp_nbr
FROM table1
) x
GROUP BY student, grp_nbr
) y
GROUP BY student
ORDER BY student
| student | max |
|---------|-----|
| 1 | 3 |
| 2 | 1 |
| 3 | 1 |
| 4 | 4 |
| 5 | 5 |

difference query between two tables in Postgresql?

In Postgresql I have table of items as follow:
id qty
1 20
2 45
3 10
it contains the quantity of each product.
I'm doing a counting operation. For every item I count I copy the data to a a log_count table. Items table NEVER CHANGED.
I want to write a query which will show me the difference between the tables. Basically how much left to pass over. When the quantity is 0 the row disappears.
This is how it should be:
Start:
items: log_count: QUERY SHOW:
1 20 1 20
2 45 2 45
3 10 3 10
after doing count of: id=1 qty=3
items: log_count: QUERY SHOW:
1 20 1 3 1 17
2 45 2 45
3 10 3 10
later, after doing count of: id=2 qty=45
items: log_count: QUERY SHOW:
1 20 1 3 1 17
2 45 2 45 3 10
3 10 * row of id 2 is gone as its qty=0
later, after doing count of: id=1 qty=2
items: log_count: QUERY SHOW:
1 20 1 5 1 15
2 45 2 45 3 10
3 10
Final stage...
items: log_count: QUERY SHOW:
1 20 1 20
2 45 2 45
3 10 3 10
How do I write this query?
Looks like a simple join to me:
select it.id, it.qty - lc.qty as difference
from items it
left join log_count lc on it.id = lc.id
where it.qty - lc.qty > 0;

Get data for a given number of days by converting rows to column dynamically

This is a follow-up to my previous question: Get records for last 10 dates
I have to generate reports for all books of a store along with sold count (if any) for the last N dates, by passing storeId.
BOOK Book Sold Store
------------ -------------------- ----------------
Id Name SID Id Bid Count Date SID Name
1 ABC 1 1 1 20 11/12/2015 1 MNA
2 DEF 1 2 1 30 12/12/2015 2 KLK
3 DF2 2 3 2 20 11/12/2015 3 KJH
4 DF3 3 4 3 10 13/12/2015
5 GHB 3 5 4 5 14/12/2015
The number of days N is supplied by the user. This is the expected output for the last 4 dates for storeId -1,2 & 3.
BookName 11/12/2015 12/12/2015 13/12/2015 14/12/2015
ABC 20 30 -- --
DEF 20 -- -- --
DF2 -- -- 10 --
DF3 -- -- -- 5
GHB -- -- -- --
If the user passes 5 than data for the last 5 days shall be generated, starting date as 14/12/2015.
I am using Postgres 9.3.
Cross table without crosstab function:
SELECT
SUM(CASE book.Date ='11/11/2015' THEN book.Count ELSE 0 END) AS '11/11/2015',
SUM(CASE book.Date ='15/11/2015' THEN book.Count ELSE 0 END) AS '15/11/2015',
SUM(CASE book.Date ='17/11/2015' THEN book.Count ELSE 0 END) AS '17/11/2015'
FROM
store,
book
WHERE
store.Id = booksold.Bid
AND store.Id IN (1,2)
GROUP BY
book.Name
ORDER BY
book.id ASC;

Comapre number range or char to get the result in oracle

RSC by comparing values from tab.col1 , tab.col2 ,tab.col3 ,tab.col4 to Result.INTR
Tab table has 1000s of rows
If any of the col1 to 4 has NULL then return 1
Col1 will hold values pertaining to RID = 10
Col2 will hold values pertaining to RID = 20
Col3 will hold values pertaining to RID = 30
Col4 will hold values pertaining to RID = 40
For eg:
if tab.col1 is 3 then 4
if tab.col2 is 'R' then 3
if tab.col3 is 1900 then it query should give 4
if 1945 then 3
if 1937 then 3 (lower bound is less than and upper bound is greater than equal to)
if tab.col4 is 6 then 5
and so on.....
Result table
RID INTR RSC
----- ----- -----
10 1 0
10 2 1
10 3 4
10 4 2
20 I 4
20 R 3
20 U 1
30 1900 5
30 1900-1937 4
30 1937-1967 3
30 1967 3
40 3-4 2
40 1-3 1
40 4 5
Check CASE and DECODE functions of Oracle.Google and check some examples.You will be able to implement your requirement with them.
For example check this one http://www.club-oracle.com/forums/case-and-decode-two-powerfull-constructs-of-sql-t181/
You would do this like:
select (case when tab.col1 = 3 then 4
when tab.col2 = 'R' then 3
when tab.col3 = 1900 then 4
when tab.col3 in (1945, 1937) then 3
when tab.col4 = 6 then 5
. . .
Try something like:
select t1.RSC, t2.RSC, t3.RSC, t4.RSC
from your_table tab join Result t1 on t1.RID=10 and t1.INTR=tab.col1
join Result t2 on t2.RID=20 and t2.INTR=tab.col2
join Result t3 on t3.RID=30 and t3.INTR >= regexp_substr(tab.col3, '^\d*') and t3.INTR <= regexp_substr(tab.col3, '\d*$')
join Result t4 on t4.RID=40 and t4.INTR >= regexp_substr(tab.col4, '^\d*') and t4.INTR <= regexp_substr(tab.col4, '\d*$')