aggregation at different levels, I need to get sum by type level in sql server - sql

ID TYPE AMT PERIOD
-------------------------------------------
1001 1 4500 2008-09-30
1001 2 2333 2008-09-30
1001 2 -2333 2008-09-30
1001 1 -200 2008-09-30
1001 2 300 2008-09-30
Desired output:
ID TYPE AMT PERIOD
------------------------------------
1001 1 4300 2008-09-30
1001 2 300 2008-09-30
I need to get sum of the AMT but still needs to include other columns, please see the desired output as shown above.
I tried using grouping sets but can't get it right.

SELECT ID,TYPE,SUM(AMT) as Total_Amt,PERIOD
FROM table
GROUP BY ID,TYPE,PERIOD

Related

SQL query to select specific fields, process sum and count from two tables

i have these two tables
ORDERS
id order_id e_id e_name
1 1000 1001 Tom
2 1009 1001 Tom
3 1010 1001 Tom
4 1011 1002 Parker
5 1012 1002 Parker
6 1013 1003 Rohan
Transactions
id order_id amount status
1 1000 100 success
2 1009 80 success
3 1010 100 failed
4 1011 50 success
6 1012 50 success
7 1013 100 failed
i would like to join two tables, select fields, process sum count and filter like this
e_id e_name amount_sum total_counts total_success_amount success_count
1001 Tom 280 3 180 2
1002 Parker 100 2 100 2
1003 Rohan 100 1 0 0
this is what i tried
use card;
SELECT COUNT(orders.order_id) as `total_counts`,
COUNT(CASE WHEN transactions.status = 'success' THEN 1 END) as `success_count`,
SUM(0 + transactions.amount) as `amount_sum`, orders.e_id,
orders.e_name
FROM orders
LEFT JOIN transactions
ON transactions.order_id=orders.order_id
GROUP BY (orders.e_id), (orders.order_id),
(orders.e_name), (transactions.amount), (transactions.status);
i tried many queries also not able to achieve it. Suggest me query to get my operation.

Showing Two Fields With Different Timeline in the Same Date Structure

In the project I am currently working on in my company, I would like to show sales related KPIs together with Customer Score metric on SQL / Tableau / BigQuery
The primary key is order id in both tables. However, order date and the date we measure Customer Score may be different. For example the the sales information for an order that is released in Feb 2020 will be aggregated in Feb 2020, however if the customer survey is made in March 2020, the Customer Score metric must be aggregated in March 2020. And what I would like to achieve in the relational database is as follows:
Sales:
Order ID
Order Date(m/d/yyyy)
Sales ($)
1000
1/1/2021
1000
1001
2/1/2021
2000
1002
3/1/2021
1500
1003
4/1/2021
1700
1004
5/1/2021
1800
1005
6/1/2021
900
1006
7/1/2021
1600
1007
8/1/2021
1900
Customer Score Table:
Order ID
Customer Survey Date(m/d/yyyy)
Customer Score
1000
3/1/2021
8
1001
3/1/2021
7
1002
4/1/2021
3
1003
6/1/2021
6
1004
6/1/2021
5
1005
7/1/2021
3
1006
9/1/2021
1
1007
8/1/2021
7
Expected Output:
KPI
Jan-21
Feb-21
Mar-21
Apr-21
May-21
June-21
July-21
Aug-21
Sep-21
Sales($)
1000
2000
1500
1700
1800
900
1600
1900
AVG Customer Score
7.5
3
5.5
3
7
1
I couldn't find a way to do this, because order date and survey date may/may not be the same.
For sample data and expected output, click here.
I think what you want to do is aggregate your results to the month (KPI) first before joining, as opposed to joining on the ORDER_ID
For example:
with order_month as (
select date_trunc(order_date, MONTH) as KPI, sum(sales) as sales
from `testing.sales`
group by 1
),
customer_score_month as (
select date_trunc(customer_survey_date, MONTH) as KPI, avg(customer_score) as avg_customer_score
from `testing.customer_score`
group by 1
)
select coalesce(order_month.KPI,customer_score_month.KPI) as KPI, sales, avg_customer_score
from order_month
full outer join customer_score_month
on order_month.KPI = customer_score_month.KPI
order by 1 asc
Here, we aggregate the total sales for each month based on the order date, then we aggregate the average customer score for each month based on the date the score was submitted. Now we can join these two on the month value.
This results in a table like this:
KPI
sales
avg_customer_score
2021-01-01
1000
null
2021-02-01
2000
null
2021-03-01
1500
7.5
2021-04-01
1700
3.0
2021-05-01
1800
null
2021-06-01
900
5.5
2021-07-01
1600
3.0
2021-08-01
1900
7.0
2021-09-01
null
1.0
You can pivot the results of this table in Tableau, or leverage a case statement to pull out each month into its own column - I can elaborate more if that will be helpful

How to write the query to make report by month in sql

I have the receiving and sending data for whole year. so i want to built the monthly report base on that data with the rule is Fisrt in first out. It means is the first receiving will be sent out first ...
DECLARE #ReceivingTbl AS TABLE(Id INT,ProId int, RecQty INT,ReceivingDate DateTime)
INSERT INTO #ReceivingTbl
VALUES (1,1001,210,'2019-03-12'),
(2,1001,315,'2019-06-15'),
(3,2001,500,'2019-04-01'),
(4,2001,10,'2019-06-15'),
(5,1001,105,'2019-07-10')
DECLARE #SendTbl AS TABLE(Id INT,ProId int, SentQty INT,SendMonth int)
INSERT INTO #SendTbl
VALUES (1,1001,50,3),
(2,1001,100,4),
(3,1001,80,5),
(4,1001,80,6),
(5,2001,200,6)
SELECT * FROM #ReceivingTbl ORDER BY ProId,ReceivingDate
SELECT * FROM #SendTbl ORDER BY ProId,SendMonth
Id ProId RecQty ReceivingDate
1 1001 210 2019-03-12
2 1001 315 2019-06-15
5 1001 105 2019-07-10
3 2001 500 2019-04-01
4 2001 10 2019-06-15
Id ProId SentQty SendMonth
1 1001 50 3
2 1001 100 4
3 1001 80 5
4 1001 80 6
5 2001 200 6
--- And the below is what i want:
Id ProId RecQty ReceivingDate ... Mar Apr May Jun
1 1001 210 2019-03-12 ... 50 100 60 0
2 1001 315 2019-06-15 ... 0 0 20 80
5 1001 105 2019-07-10 ... 0 0 0 0
3 2001 500 2019-04-01 ... 0 0 0 200
4 2001 10 2019-06-15 ... 0 0 0 0
Thanks!
Your question is not clear to me.
If you want to purely use the FIFO approach, therefore ignore any data the table contains, you necessarely need to order by ID, which in your example you are providing, and looks like it is in order of insert.
The first line inserted should be also the first line appearing in the select (FIFO), in order to do so you have to use:
ORDER BY Id ASC
Which will place the lower value of the ID first (1, 2, 3, ...)
To me though, this doesn't make much sense, so pay attention to the meaning o the data you actually have and leverage dates like ReceivingDate, and order by that, maybe even filtering by month of the date, below an example for January data:
WHERE MONTH(ReceivingDate) = 1

Need help on Query

Table_Name : Order_trans_detail
Order_id Order_date Order_qty Item_id order_amount
100 12-Jan-16 1 1001 20
101 13-Feb-15 4 1001 80
103 14-Mar-16 3 1001 60
104 16-Dec-15 9 1001 180
105 17-Jan-16 1 1001 20
106 18-Feb-16 4 1001 80
107 19-Feb-16 3 1001 60
108 20-Jan-15 9 1001 180
109 21-Mar-15 3 1001 60
110 21-Apr-15 3 1001 60
Need Query to identify how many orders placed in Month of Feb-2016 as to display Month Name and count.
You need to use DATENAME and YEAR function to extract Month name and Year from date and use it in Group by to get the count
select DATENAME(MONTH,Order_date ),YEAR(Order_date), Count(*)
From Order_trans_detail
Group by DATENAME(MONTH,Order_date ),YEAR
To filter the records add Where clause
Where DATENAME(MONTH,Order_date ) = 'february' and YEAR(Order_date) = 2016
To get the result in Mon-year format use this in Select
DATENAME(MONTH,Order_date )+'-'+cast(YEAR(Order_date) as char(4))
If you are using SQL Server 2012+ to concatenate month and year use CONCAT function
CONCAT(DATENAME(MONTH,Order_date ),'-',YEAR(Order_date))
Advantage of using CONCAT is that you don't need to perform explicit conversion when concatenating Int with Varchar

Selecting the last instance of the record but returning the first instance of it

I have table that consist logs of calls.
callid calling_pty dialed_num disposition dispvdn segment ucid
3862073 25555366 1001 1 1001 1 10000080561437527378
3862073 291113 1015 2 1015 2 10000080621437527416
3862074 635444419 1001 3 1001 1 10000081311437527892
3862075 25555596 1001 1 1001 1 10000081211437527803
3862075 26669 1014 3 1014 2 10000081231437527820
3862076 23044442 1009 2 1009 1 10000080961437527654
3862079 632444419 1001 1 1001 1 10000081361437527904
3862089 0111808 1001 1 1001 1 10000081671437528068
3862091 02366674 1001 1 1001 1 10000081011437527679
3862091 26666 1015 2 1015 2 10000081091437527712
3862097 63255529 1001 1 1001 1 10000081721437528139
3862097 29111 1014 3 1014 2 10000081771437528168
Given the sample data, I need to select the records with disposition = 3, but I need to check first if it has an earlier segment [disposition is the status of the call, 3 for abandon and segment is the number of call instances if it is transferred or not in one transaction]. and return the calling_pty(caller number) of the first instance, hence if there is none, it will return the number of that record. And it can be identifiend with the help of the callid
So with the given sample,
3862075 25555596 1001 1 1001 1 10000081211437527803
3862075 26669 1014 3 1014 2 10000081231437527820
it will return to me "25555596", they have the same callid but different calling party which would mean the call was transferred and then it was abandoned.
Therefore: the resulting record should be the "25555596" record.
*This would apply to all records of the same conditions and it will be populated as a list
3862074 635444419 1001 3 1001 1 10000081311437527892
3862075 25555596 1001 1 1001 1 10000081211437527803
3862097 63255529 1001 1 1001 1 10000081721437528139
*this will be the end result for the sample data
I did a nested select but im on the dead end of how I will check for the first instance. is there a sql function to achieve this?
I used two correlated sub-queries:
SELECT callid,
(SELECT calling_pty
FROM Log l
WHERE Log.callid = l.callid AND
segment = (SELECT MIN(segment)
FROM Log l2
WHERE l.callid = l2.callid)
)[calling_pty],
dialed_num, disposition, dispvdn, segment, ucid
FROM Log
WHERE disposition = 3
SQL Fiddle Demo