SQL Query Join plus sum and months sorting - sql-server

i have a problem using the sum function with the inner join in the below query
SELECT distinct Datename(Month,(date)), year(date), SUM(tblpayment.Amount)
FROM TblSubsc INNER JOIN TBLPayment ON
TblSubsc.[Subsc ID]=TBLPayment.[Subsc ID]
group by year(date),Datename(Month,(date))
it is giving the sum but the months are not sorted so i get
April
August
February
January
March
May
please any help would be appreciated

Try to add the order by clause
order by year(date) asc, month(date) asc
and add
month(date)
to group by too.
EDIT: remove "distinct" as it's not necessary in this case because the data is already grouped by month & date.

Related

AdventureWorks in SQL Server 2019 : ordershare percent for each item per month

I'm new to SQL Server. I'm trying to write a code to find the sale percent/per item/per month. Something like this:
Year
Month
ProductID
Order_Quantity_Per_Month
Total_Sold_Per_Month
%_Of_Total_Sale
2011
5
707
422
17024
2
First and most importantly, I want to write this code with "CTE" and "Group by". I've tried many times but I failed. How can I write this code with cte and group by?
I wrote this code with "Over" and "Partition". Could someone check the codes I've written to see if it's actually correct:
USE AdventureWorks2019
GO
SELECT
YEAR (soh.OrderDate) As Year,
MONTH (soh.OrderDate) As Month,
pro.productid AS [Product ID],
pro.Name AS [Product Name],
SUM(sod.OrderQty) OVER (PARTITION BY Month(soh.OrderDate) ORDER BY by soh.OrderDate) AS [Order Quantity Per Month],
SUM(sod.OrderQty) OVER (PARTITION BY Month(soh.OrderDate)) AS [Total Sold Per Month],
SUM(sod.OrderQty) OVER (PARTITION BY Month(soh.OrderDate) ORDER BY by soh.OrderDate) * 100 / SUM(sod.OrderQty) OVER (PARTITION BY Month(soh.OrderDate)) AS [% of TotalSale]
FROM
Production.Product pro
INNER JOIN
Sales.SalesOrderdetail sod ON pro.ProductID = sod.ProductID
INNER JOIN
Sales.SalesOrderheader soh ON soh.SalesOrderID = sod.SalesOrderID
GROUP BY
YEAR(soh.OrderDate), MONTH(soh.OrderDate),
soh.OrderDate, pro.productid, pro.Name, sod.OrderQty
ORDER BY
Year, Month
If the above code is correct, How can I write the code with cte and group by?
I think the better question is why you want (or need) to use a CTE. A simple CTE (i.e., not recursive) is just syntactic sugar for a derived table. There is nothing particular special or complicated about writing and using one in a query. If you "tried many times", you should have included those attempts in your question.
But to satisfy the need to use a CTE, you can simply "cram" the query you have into the CTE and select rows from it. Example:
with cteOrders as (
select ... -- your original query here without ORDER BY clause
)
select * from cteOrders
order by [Year], [Month]
;
That is a extremely simplistic way of using a CTE. There is no real or obvious advantage to doing so but it does satisfy your goal. Because of that, I smell a XY problem.

How to create a week counter?

Example of what I am trying to do:
I have 10 employees. They all started on different days throughout the year. Each potentially gets paid once a week. I want to query their first paycheck and call that week 1 for all employees. Then each subsequent paycheck will be 2...3...through 13. So basically I want to see what each of their first 13 weeks on the job looked like stacked against each other. The catch here is the potentially above. Employees might not get paid each week so I would want to see a zero for that week. I know this is tough because there is no record to read for that week. I would expect my output to look something like this:
I was thinking of using a Tally Table of some kind and reading their hire date +7 over an over? I am open to any idea.
You can use Row_Number() as shown below.
SELECT Week
,EmployeeId
,[Paycheck Date]
,Amount
,Row_Number() OVER (
PARTITION BY EmployeeId ORDER BY [Paycheck Date]
) AS WkNo
FROM Yourtable
To create and join with the Week Number table you can try something as shown below.
;WITH WeekTable(n) AS
(
SELECT 1
UNION ALL
SELECT n + 1 FROM WeekTable WHERE n < 52
)
SELECT
n
FROM WeekTable
left join (SELECT Week
,EmployeeId
,[Paycheck Date]
,Amount
,Row_Number() OVER (
PARTITION BY EmployeeId ORDER BY [Paycheck Date]
) AS WkNo
FROM Yourtable)emp on n = emp.WkNo
ORDER BY n
OPTION (MAXRECURSION 1000);

Join tables then sum on distinct values

I'm working through some Adventureworks Challenges, and I'm trying to whittle down/summarize a joined table.
The following correctly joins my two tables and produces 3 columns:
use AdventureWorks2012
select datename(dw,orderdate ) as "Day", LineTotal,OrderQty
from sales.SalesOrderDetail join sales.SalesOrderHeader
on (SalesOrderDetail.SalesOrderID=SalesOrderHeader.SalesOrderID)
Adjusting it slightly, results in a table that shows only the distinct dates of Monday, tuesday, wednesday, etc...
use AdventureWorks2012
select distinct(datename(dw,orderdate)) as "Day"
from sales.SalesOrderDetail join sales.SalesOrderHeader
on (SalesOrderDetail.SalesOrderID=SalesOrderHeader.SalesOrderID)
I'm trying to figure out how to produce the sum of LineTotal and the sum of OrderQty per day, but not having success.
The closest I've gotten is the following:
use AdventureWorks2012
select distinct(datename(dw,orderdate)) as "Day", sum(LineTotal), SUM(OrderQty)
from sales.SalesOrderDetail join sales.SalesOrderHeader
on (SalesOrderDetail.SalesOrderID=SalesOrderHeader.SalesOrderID)
group by OrderDate
However, this produces many, many rows, instead of just 7 rows and the accompanying totals of LineTotal, OrderQty.
Thanks for any suggestions.
use AdventureWorks2012
select
datename(dw,orderdate ) as "Day",
SumLineTotal=SUM(LineTotal),
SumOrderQty=SUM(OrderQty)
from
sales.SalesOrderDetail
INNER join sales.SalesOrderHeader on (SalesOrderDetail.SalesOrderID=SalesOrderHeader.SalesOrderID)
group by
datename(dw,orderdate)
I don't have adventure works but pretty sure you could do something like this. Notice I am using aliases here to make this a little easier. Also, using datepart and the long hand date part instead of short hand. The short hand version is difficult to remember.
select OrderDay = datepart(dayofweek, soh.OrderDate)
, sum(sod.LineTotal)
, SUM(sod.OrderQty)
from sales.SalesOrderDetail sod
join sales.SalesOrderHeader soh on sod.SalesOrderID = soh.SalesOrderID
group by datepart(dayofweek, soh.OrderDate)
use AdventureWorks2012
select datename(dw,orderdate) as "Day", sum(LineTotal), SUM(OrderQty)
from sales.SalesOrderDetail join sales.SalesOrderHeader
on SalesOrderDetail.SalesOrderID=SalesOrderHeader.SalesOrderID
group by datename(dw,orderdate)
When used, it is the group by clause that controls the formation of rows, not the select clause. So use the datename function on the orderdate column in the group by clause.
Also, please note that distinct is not a function. so parentheses after the word distinct mean nothing, in fact they are ignored.
Do NOT use select distinct when using group by, it is redundant.

Max(datetime) ignore seconds

I got my sql query working but when I find a date with the same hour and minutes, I am not able to make the query works. For example:
On the column "trans_date" I can't use my query because with max(trans_date) I am getting no results, somehow the sql is ignoring the seconds.
This is my complete sql sentence:
SELECT till.code,art.description
FROM [TCPOS4].[dbo].[transactions] as tra,
TCPOS4.dbo.articles as art,[TCPOS4].[dbo].[trans_articles] as tro,
[TCPOS4].[dbo].[tills] as till,[TCPOS4].[dbo].[shops] as shop
where tra.till_id=till.id and shop.id=till.shop_id and tro.transaction_id=tra.id and
art.id=tro.article_id and tra.trans_date =(select max(trans_date)
from tcpos4.dbo.transactions as t2 where t2.till_id=tra.till_id and trans_date > '2016-10-26 00:00:0.000' and trans_date< '2016-10-27 00:00:00.000' )
group by till.code,art.description
With this query I am getting for each "code" from the 2016-10-26 to 2016-10-27 the max transaction_date, but I am not getting any information from the code "5446". I should get "TABLE CHOCOLECHE-CONGUITOS" because it's the max trans_date in the range.
Can you try with a different approach like the following?
SELECT code, description
FROM
(
SELECT till.code, art.description,
row_number() OVER (PARTITION BY till.code ORDER BY trans_date DESC) RowNum
FROM [TCPOS4].[dbo].[transactions] AS tra
LEFT JOIN [TCPOS4].[dbo].[tills] AS till
ON tra.till_id=till.id
LEFT JOIN [TCPOS4].[dbo].[shops] AS shop
ON shop.id=till.shop_id
LEFT JOIN [TCPOS4].[dbo].[trans_articles] AS tro
ON tro.transaction_id=tra.id
LEFT JOIN TCPOS4.dbo.articles AS art
ON art.id=tro.article_id
) sbt
WHERE RowNum=1
In this way you will get one result for each till.code even if you have the same exact date.
You can add more fields in the ORDER BY if needed.
EDIT: removed art.description in PARTITION BY.
EDIT 2: converted with LEFT JOIN
try
...CAST(tra.trans_date AS DATE) = (select CAST(max(trans_date) AS DATE)...

SQl query to sum-up amounts by month/year

I have a table "TABLE" like this:
Date(datatime)
Paid(int)
I have multiple "Paid" amounts per month.
I would like to sum up the Paid amount per month/year.
So far this is what I tried but I get errors in EXTRACT and in MONTH and however I am far to get it done with the years.
SELECT
EXTRACT(MONTH FROM Period) AS reference_month
, SUM(Paid) AS monthly_payments
FROM Paid
GROUP BY EXTRACT(MONTH FROM Period)
ORDER BY EXTRACT(MONTH FROM Period)
I am not really handy at this and I would really appreciate some help.
select year(date) as y, month(date) as m, sum(paid) as p
from table
group by year(date), month(date)
SELECT YEAR([Date]) AS [Year], MONTH([Date]) AS [Month], SUM(Paid) AS Total
FROM TABLE_NAME
GROUP BY YEAR([Date]), MONTH([Date])
You need to use square brackets around your objects name [] when you have named your object with sql server key words.

Resources