Sum of sales by customer from two monthly sales tables - efficient query - sql-server

looking for most efficient query to sum the cost by customer for both months - there are two tables, one for Jan and one for Feb.
Would I do an inner join or a proc sql? Looking for help. Thanks!
Added an image above because columns didn't stay in order when i typed below.
desired result:
cust 1 total from both tables
cust 2 total from both tables
cust 3 total from both tables
mo cust $ item
jan cust1 10 shoe
jan cust1 20 coat
jan cust1 30 misc
jan cust2 11 shoe
jan cust2 22 top
jan cust3 30 jean
mo cust $ item
feb cust1 15 misc
feb cust1 20 misc
feb cust1 25 jean
feb cust2 35 jean
feb cust3 12 top
feb cust3 30 top

Can only be as efficient as your table deign. I assume "$" isn't the actual column name:
select
cust, sum(dollars) as dollars
from (
select cust, dollars from table1
UNION ALL
select cust, dollars from table2
) d
group by
cust

Related

Break Quarter into Months in SQL Server

I want to break the quarters into months. In source I have 2019Q1 but I need to break the one record into 3 records
empid Quarter earnings
-----------------------
123 2019Q1 4000
456 2019Q2 6000
Desired result:
mpid Month earnings
---------------------------
123 January 2019 4000
123 February 2019 4000
123 March 2019 4000
456 April 2019 6000
456 May 2019 6000
456 June 2019 6000
As Larnu suggested, a Calendar Table is well worth the effort. That said, here is an option that performs a 1-to-many join to an ad-hoc table
Example
Select empid
,MonthYear = datename(month,datefromparts(left(Quarter,4),MM,1))+' '+left(Quarter,4)
,Earnings
From YourTable A
Join (
Select *
From ( values (1,1)
,(1,2)
,(1,3)
,(2,4)
,(2,5)
,(2,6)
,(3,7)
,(3,8)
,(3,9)
,(4,10)
,(4,11)
,(4,12)
)B1(QQ,MM)
) B on right(Quarter,1)=QQ
Results
empid MonthYear Earnings
123 January 2019 4000
123 February 2019 4000
123 March 2019 4000
456 April 2019 6000
456 May 2019 6000
456 June 2019 6000
If you don't need the "earnings" value by month, then you just need to setup a CTE to match the Q# with the corresponding months and add that to your query.

SQL Server query for Total of hours across multiple rows

I've tried to resolve this a few ways and wanting some extra help.
I'm wanting to return the same number of rows but trying to calculate the number of total hours delivered by each Employee for each service on each day.
I've added a duplicate flag but that doesn't help me to work out the max hours by the 1 employee in 1 day.
Emp Service Date Start End Hrs Duplicate Flag Flag hrs
Fred xyz 14/09/2017 8:45 15:00 6.25 1 1 6.25
Fred xyz 14/09/2017 9:00 14:15 5.25 1 0 0
Fred xyz 14/09/2017 9:00 14:15 5.25 2 0 0
Fred xyz 14/09/2017 9:00 15:00 6 1 0 0
John xyz 15/09/2017 10:00 12:00 2 1 1 2
John xyz 15/09/2017 10:00 13:00 3 1 0 0
John xyz 15/09/2017 11:00 15:00 4 1 0 0
John xyz 15/09/2017 12:00 16:00 4 1 1 4
the last 2 columns are the ones I can't quite work out how to add. I've tried Overlaps and other ANDing methods.
thanks, Dave
I think you are looking for an OVER clause. Not sure what the duplicate flag is for though? If you ignore your last three columns, assuming they are computed columns in a query, you could use...
Select
*,
sum(Hrs) over (partition by Emp, Date, Service order by Date)
From (select distinct * from your table) x
If the last three columns are actual columns in your table just replace select * in the derived table with the column names, except those three.

Conditional calculation in SQL Server

friends:
I'm now have a problem about conditional calculation in SQL Server.
I have set some data from SQL Server as an example in excel like this:
No Employee Month Commission1 Commission2
1 A Jan 10 5
2 A Jan 10 4
3 B Jan 15 3
4 B Jan 15 4
5 C Jan 10 3
6 C Jan 10 4
7 D Jan 13 3
8 D Jan 13 4
9 DM Jan 0 6
10 DM Jan 0 8
11 A Feb 15 4
12 A Feb 15 5
13 B Feb 20 5
14 B Feb 20 4
15 C Feb 9 3
16 C Feb 9 4
17 D Feb 14 5
18 D Feb 14 6
19 DM Feb 0 13
20 DM Feb 0 10
And the result I want is like this:
Employee Jan No# Feb No#
A 20 2 30 2
B 30 2 40 2
C 20 2 18 2
D 26 2 28 2
DM 44 10 59 10
For every sales,Employee A,B,C,D only have commission1 as payment,the commission2 is for DM. So , in Jan , DM's commission is SUM(E2:E9)
I can do it easy in excel , but how can I do this in sql server?
I make my try code like this:
select [Month],Employee,SUM(Commission1) Commission,count(distinct([No])) No#
from table1
WHERE Employee IN ('A','B','C','D')
group by [Month],Employee
union
select 'DM' as Employee,[Month],SUM(Commission2) Commission,count(distinct([No])) No#
from table1
WHERE Employee IN ('A','B','C','D','DM')
group by [Month],Employee
And I get the result
Employee Month Commission No#
A Jan 20 2
B Jan 30 2
C Jan 20 2
D Jan 26 2
DM Jan 44 10
A Feb 30 2
B Feb 40 2
C Feb 18 2
D Feb 28 2
DM Feb 59 10
The result format is not what I want.I tried pivot after this query,but failed,it seems I only can pivot one state?
Another question: If I want the month growth automatic (In actual data , there's not only Jan and Feb) in the result ,not write [Jan],[Feb],[Mar]... in pivot code, how to do it?
Who can help me?
Thanks!
Here is a PIVOT solution:
Test data:
DECLARE #t table(Employee varchar(2), Month char(3), Commission1 int, Commission2 int)
INSERT #t values
('A','Jan',10,5 ),('A','Jan',10,4),('B','Jan',15,3),
('B','Jan',15,4 ),('C','Jan',10,3),('C','Jan',10,4),
('D','Jan',13,3 ),('D','Jan',13,4),('DM','Jan',0,6),
('DM','Jan',0,8 ),('A','Feb',15,4),('A','Feb',15,5),
('B','Feb',20,5 ),('B','Feb',20,4),('C','Feb',9,3),
('C','Feb',9,4 ),('D','Feb',14,5),('D','Feb',14,6),
('DM','Feb',0,13),('DM','Feb',0,10)
Query:
;WITH CTE as
(
SELECT
Employee, Month,
CASE WHEN Employee = 'DM' THEN
SUM(Commission2) over (partition by [Month])
ELSE Commission1 END com,
CASE WHEN Employee = 'DM'
THEN row_number() over
(PARTITION BY Employee, [Month] ORDER BY (SELECT 1)) ELSE 1 END rn
FROM #t
)
SELECT Employee, [Jan], [Feb], [Mar] -- add more months
FROM
CTE
PIVOT
(SUM(com)
FOR [Month] IN ([Jan], [Feb], [Mar])) AS pvt -- add more months
WHERE rn = 1
Result:
Employee Jan Feb Mar
A 20 30 NULL
B 30 40 NULL
C 20 18 NULL
D 26 28 NULL
DM 44 59 NULL
In SqlServer you can do so using PIVOT operator as like below:
Please refer PIVOT syntax
select tmp.employee,pv.[jan] as Jan_Commission, pv.[feb] as Feb_Commission from
(
select employee,month,commission1 from table_name
)tmp
pivot (
sum(commission1)
for [month] in ([jan],[feb])
)pv;

Query to compare two year sales

I have a table in SQL Server with these columns:
Year
Month
Product
Qty
Example:
Year Month Product Qty
2011 1 XYZQW 45
So in this table was stored all product sales.
I need to build a query to compare one year and its previous to build this report:
Year GEN FEB MAR APR MAY GIU JUL AUG SEP OCT NOV DEC
-------------------------------------------------------
2011 12 23 56 54 14 11 15 18 89 87 48 98
2012 19 21 55 50 24 10 19 17 88 81 45 90
There is a way to do this without creating a temporary table?
This is simple, try this:
WITH DT(AMonth,AYear,AQty)
AS (SELECT Month, Year, Qty
FROM YourTable)
SELECT pvt.*
FROM DT cte
PIVOT
(SUM(AQty)
FOR AYear IN ( [2011],[2012],[2013],[2014] ) ) AS pvt

sql server - help in query

I have a table called employee_salary_master in which we keep salary effective dates and entry dates of each employee in the company.
For processing salary of an employee for a month, we need to fetch most recently entered record. If the effective date is less than
that month then we pick the most recent entry. but if effective date is greater than the first date of the month, then there will be more than
one effective dates for that month
example: the data for an employee is as below.
SAL_MATSER_ID EMPLOYEE_ID EFFECTIVE_DATE ENTRY_DATE
------------- ----------- -------------- ------------
1 5814 Jan 6 2006 Jan 12 2006
2 5814 Jan 10 2006 Jul 17 2006
3 5814 Jan 20 2006 Dec 22 2006
4 5814 May 10 2007 Jul 18 2007
5 5814 Nov 1 2007 Dec 18 2007
6 5814 Aug 1 2008 Aug 20 2008
7 5814 May 1 2008 Sep 2 2008
8 5814 Sep 1 2009 Sep 18 2008
9 5814 Nov 1 2008 Apr 20 2009
10 5814 Nov 10 2009 Nov 25 2009
11 5814 Nov 5 2009 Nov 26 2009
If i need to get the record for Nov 2009, I write the query below
select EMPLOYEE_SALARY_MASTER_ID, EMPLOYEE_ID, EFFECTIVE_DATE, ENTRY_DATE, ARREAR_PROCESS_FLAG from employee_salary_master esm where employee_id = 5814
and (esm.entry_date = (select max(entry_date) from employee_salary_master where employee_id = 5814 and effective_date <= #monthfirstdate)
or (esm.effective_date between #monthfirstdate and #monthlastdate))
which gives the result below..
SAL_MATSER_ID EMPLOYEE_ID EFFECTIVE_DATE ENTRY_DATE
------------- ----------- -------------- ------------
9 5814 Nov 1 2008 Apr 20 2009
10 5814 Nov 10 2009 Nov 25 2009
11 5814 Nov 5 2009 Nov 26 2009
What I need is as follows...
For Nov 1 - Nov 4, salary should be processed as per employee_salary_masterId - 9 and
Nov 5 - Nov 30, salary should be processed as per employee_salary_masterId - 11.
SAL_MATSER_ID EMPLOYEE_ID EFFECTIVE_DATE ENTRY_DATE
------------- ----------- -------------- ------------
9 5814 Nov 1 2008 Apr 20 2009
11 5814 Nov 5 2009 Nov 26 2009
Please help me build this query.
Not quite sure if I understand you completely correct, but have a look at this example
DECLARE #employee_salary_master TABLE(
EMPLOYEE_SALARY_MASTER_ID INT,
EMPLOYEE_ID INT,
EFFECTIVE_DATE DATETIME,
ENTRY_DATE DATETIME
)
INSERT INTO #employee_salary_master SELECT 1,5814,'Jan 6 2006','Jan 12 2006'
INSERT INTO #employee_salary_master SELECT 2,5814,'Jan 10 2006','Jul 17 2006'
INSERT INTO #employee_salary_master SELECT 3,5814,'Jan 20 2006','Dec 22 2006'
INSERT INTO #employee_salary_master SELECT 4,5814,'May 10 2007','Jul 18 2007'
INSERT INTO #employee_salary_master SELECT 5,5814,'Nov 1 2007','Dec 18 2007'
INSERT INTO #employee_salary_master SELECT 6,5814,'Aug 1 2008','Aug 20 2008'
INSERT INTO #employee_salary_master SELECT 7,5814,'May 1 2008','Sep 2 2008'
INSERT INTO #employee_salary_master SELECT 8,5814,'Sep 1 2009','Sep 18 2008'
INSERT INTO #employee_salary_master SELECT 9,5814,'Nov 1 2008','Apr 20 2009'
INSERT INTO #employee_salary_master SELECT 10,5814,'Nov 10 2009','Nov 25 2009'
INSERT INTO #employee_salary_master SELECT 11,5814,'Nov 5 2009','Nov 26 2009'
DECLARE #monthfirstdate DATETIME,
#monthlastdate DATETIME
SELECT #monthfirstdate = '01 Nov 2009',
#monthlastdate = '30 Nov 2009'
SELECt *
FROM (
SELECT TOP 1
*
FROM #employee_salary_master esm
WHERE esm.EFFECTIVE_DATE BETWEEN #monthfirstdate and #monthlastdate
AND esm.EFFECTIVE_DATE < esm.ENTRY_DATE
ORDER BY esm.ENTRY_DATE DESC
) sub
UNION ALL
SELECT *
FROM (
SELECT TOP 1
*
FROM #employee_salary_master esm
WHERE esm.EFFECTIVE_DATE <= #monthfirstdate
AND esm.EFFECTIVE_DATE < esm.ENTRY_DATE
ORDER BY esm.EFFECTIVE_DATE DESC
) sub
ORDER BY EFFECTIVE_DATE
The rule for excluding nov 10 record is that we need to filter out those records for the month of November in which entry_date is greater but effective_date is smaller.
Let me explain you wrt data provided:
As a rule, the latest/last entry will take precedence over the previous entries in a particular month which implies that the entrty date of Nov 26 2009 would take precedence over the entry date of Nov 25 2009. Now since effective date of SAL_MATSER_ID - 10 is greater than that of SAL_MATSER_ID - 11, hence Nov 10 record would be nullified.
Had the data been like the below, all the 3 records would have been used for salary processing.
SAL_MATSER_ID - 9 for salary of Nov 1 - Nov 9
SAL_MATSER_ID - 10 for salary of Nov 10 - Nov 14
SAL_MATSER_ID - 11 for salary of Nov 15 - Nov 30
SAL_MATSER_ID EMPLOYEE_ID EFFECTIVE_DATE ENTRY_DATE
------------- ----------- -------------- ------------
9 5814 Nov 1 2008 Apr 20 2009
10 5814 Nov 10 2009 Nov 25 2009
11 5814 Nov 15 2009 Nov 26 2009
But since SAL_MATSER_ID - 11 is applicable from 5th Nov. onwards, the previous record is nullified. I hope this explains the situation.
Thanks for your support,
Sweta

Resources