Sum by month in SQL - sql

I am trying to sum my daily data (trunc(DM_OWNER.LD_LEG_DW.CPLD_DTT) by month. This is created in a Web Intelligence BI report.
SELECT
DM_OWNER.LD_LEG_DW.LGST_GRP_CD,
DM_OWNER.LGST_GRP_T.LGSTGRP_DESC,
DM_OWNER.LD_LEG_DW.CARR_CD,
DM_OWNER.LD_LEG_DW.LD_LEG_ID,
DM_OWNER.LD_LEG_DW.BILL_TO_CUST_CD,
trunc(DM_OWNER.LD_LEG_DW.CPLD_DTT),
trunc(DM_OWNER.VCHR_AP_T.CRTD_DTT),
AP_Detail.PYMNT_AMT_DLR
FROM
DM_OWNER.LD_LEG_DW,
DM_OWNER.LGST_GRP_T,
DM_OWNER.VCHR_AP_T,
DM_OWNER.CHRG_DETL_T_NOTOTAL_V AP_Detail
WHERE
( DM_OWNER.LD_LEG_DW.LD_LEG_ID=DM_OWNER.VCHR_AP_T.LD_LEG_ID(+) )
AND ( DM_OWNER.VCHR_AP_T.VCHR_NUM=AP_Detail.VCHR_NUM_AP )
AND ( DM_OWNER.LD_LEG_DW.LGST_GRP_CD=DM_OWNER.LGST_GRP_T.LGST_GRP_CD )
AND
(
DM_OWNER.LD_LEG_DW.LGST_GRP_CD In ( 'PBRK' )
AND
trunc(DM_OWNER.VCHR_AP_T.CRTD_DTT) >= '01-10-2012 00:00:00'
)

Without clear field names, or an explanation of the data structure, this is too vague. But the principle is
select
displayfields,
year(datefield), month(datefield),
sum(valuefield)
from yourtable
group by
displayfields,
year(datefield), month(datefield),

Without getting into the specifics of your query, here's a general approach.
The CAST is nasty, but this has the benefit of giving you an actual DATETIME as a grouper.
SELECT
SUM(Amount) AS MonthTotal,
CAST(CAST(YEAR(DateCollected) AS VARCHAR(4))
+ '/' + CAST(MONTH(DateCollected) AS VARCHAR(2))
+ '/01' AS DATETIME) AS PaymentMonth
FROM
PaymentsReceived
GROUP BY
CAST(CAST(YEAR(DateCollected) AS VARCHAR(4))
+ '/' + CAST(MONTH(DateCollected) AS VARCHAR(2)) + '/01' AS DATETIME)

Related

How to count events based on parsing date - GROUP BY issues

I am attempting to count how many FAILURE events occurred per day, and the events are stored in a MainEventTable with columns of EventDateTime, EventId, and EventStatus. I'm using SQL Server Management Studio 2016, and it didn't recognize the DATEFROMPARTS function. This is the code that I've put together so far:
SELECT
t.EventDate,
SUM(t.EventCount) AS EventCount
FROM (
SELECT
CAST(
(
CAST(
DATEPART(yyyy,s.EventDateTime)
AS VARCHAR(4)
) + '-' +
CAST(
DATEPART(mm,s.EventDateTime)
AS VARCHAR(2)
) + '-' +
CAST(
DATEPART(dd,s.EventDateTime)
AS VARCHAR(2)
)
) AS DATE
) AS EventDate,
Count(s.EventId) AS EventCount
FROM (
SELECT
EventDateTime,
EventId
FROM
MainEventTable WITH(NOLOCK)
WHERE EventDateTime > '2016-12-07 00:00:00'
AND EventStatus = 'FAILURE'
) AS s GROUP BY CAST(
(
CAST(
DATEPART(yyyy,s.EventDateTime)
AS VARCHAR(4)
) + '-' +
CAST(
DATEPART(mm,s.EventDateTime)
AS VARCHAR(2)
) + '-' +
CAST(
DATEPART(dd,s.EventDateTime)
AS VARCHAR(2)
)
) AS VARCHAR(10)
)
) AS t
GROUP BY t.EventDate;
UPDATE: (THANKS to #wrslphil and #PM_77-1 for assistance with my GROUP BY issues) I've fixed my GROUP BY issues above and found that this worked, although it was very clunky. #KeithL simplified it MUCH more below...
Not a lot to go on here, but the query definitely won't run if you have an item that isn't in the group by list or aggregated in your select clause
I would think that you probably need to do a sum of your count field... like so
SELECT
t.EventDate,
SUM(t.EventCount) as EventCount
FROM (
SELECT
CAST(
(
CAST(
DATEPART(yyyy,s.EventDateTime)
AS VARCHAR(4)
) +
CAST(
DATEPART(mm,s.EventDateTime)
AS VARCHAR(2)
) +
CAST(
DATEPART(dd,s.EventDateTime)
AS VARCHAR(2)
)
) AS DATE
) AS EventDate,
Count(s.EventId) As EventCount
FROM (
SELECT
EventDateTime,
EventId
FROM
MainEventTable WITH(NOLOCK)
WHERE EventDateTime > '2016-12-07 00:00:00'
AND EventStatus = 'FAILURE'
) AS s
) AS t
GROUP BY t.EventDate;
The query is still unlikely to run because you have the same issue in your inner query. I would probably just do the transformation of the date within an inner query and encapsulate it with a query containing a count and group by
select CAST(EventDateTime AS DATE),COUNT(*)
FROM MainEventTable
WHERE EventDateTime > '2016-12-07 00:00:00'
AND EventStatus = 'FAILURE'
GROUP BY CAST(EventDateTime AS DATE)
Your sub-query has the following structure:
SELECT field1, COUNT(field2)
FROM theTable
In the same select you use a "raw" field and aggregation (COUNT). You do not have GROUP BY clause.
You are confusing your SQL engine, since it's impossible to figure out what value of field1 should be picked.
If you intention was to count how many records with non-NULL value of field2 each value of field1 has then the code would be:
SELECT field1, COUNT(field2)
FROM theTable
GROUP BY field1

Update a column with records from current row in SQL Server

I have an existing SQL Server table Employees with 3 columns month, year and day as date parts.
Now I have added a new column createdate where I want to insert date as a combination of all 3 columns from the current row.
UPDATE Employees
SET createdate = TRY_PARSE(CAST([year] AS VARCHAR(4)) + '/' + CAST([month] AS VARCHAR(2)) + '/' + CAST([day] AS VARCHAR(2)) AS DATETIME)
If you have invalid data in Month Or Year Or Day Colunm, then above query will update with NULL Value.
NOTE: Try_Parse will work from Sql Server Version 2012 onwards.
You can as the below:
UPDATE Employees
SET createdate = CAST(CAST(year AS VARCHAR(4)) + '.' + CAST(month AS VARCHAR(2)) + '.' + CAST(day AS VARCHAR(2)) AS DATETIME)
You can use DATEFROMPARTS very simple to form date
UPDATE Employees SET CreateDate =DATEFROMPARTS ( year, month, day )
Try this, it's update for all rows :
UPDATE Employees SET CreateDate = [day] +'/'+ [Month] +'/'+ [year]
1)...UPDATE Employees
set createdate =
CAST(
CAST(year AS VARCHAR(4)) +
RIGHT('0' + CAST(month AS VARCHAR(2)), 2) +
RIGHT('0' + CAST(day AS VARCHAR(2)), 2)
AS DATETIME)
2)...SELECT
DATEADD(year, [year]-1900, DATEADD(month, [month]-1, DATEADD(day, [day]-1, 0)))
FROM
dbo.Table
UPDATE emp SET CreateDate =( SELECT CONVERT(DATE,CAST([Year] AS VARCHAR(4))+'-'+
CAST([Month] AS VARCHAR(2))+'-'+
CAST([Day] AS VARCHAR(2))))
or
you can also use this code:
UPDATE empl SET CreateDate =( SELECT CONVERT(varchar(10),
CAST([Month] AS VARCHAR(2))+'-'+
CAST([Day] AS VARCHAR(2))+'-'+CAST([Year] AS VARCHAR(4)),101))

How to get min date with date part in SQL

I would like to ask how to get MIN DatePart from a DateTime column in a SQL Server Select query.
This is my query:
SELECT
MIN(CAST(DATEPART(DD, DateCreated) AS NVARCHAR) +
N'/' +
CAST(DATEPART(MM, DateCreated) AS NVARCHAR) +
N'/' +
CAST(DATEPART(YYYY, DateCreated) AS NVARCHAR)) AS DateFrom
FROM
[User]
The result should be 04/04.2013 but right now, the result is 01/04/2014
Please help ....
SELECT MIN(CAST(DATEPART(DD,DateCreated) AS NVARCHAR) +
N'/' +
CAST(DATEPART(MM,DateCreated) AS NVARCHAR) +
N'.' +
CAST(DATEPART(YYYY,DateCreated) AS NVARCHAR)) AS DateFrom
FROM [User]
use the aggregation query like below one
select min(date) from tablename

SQL Server ORDER BY when using DATENAME function

SELECT CAST(DATEPART(yyyy,DATE1)
AS varchar (5)) + '-' + CAST(DATENAME(m,ec2.DATE2)
AS varchar(3)) AS [Month],
CAST(AVG(CAST(DATEDIFF(day,DATE1, DATE2)
AS DECIMAL(10,2))) AS DECIMAL(10,2)) AS tt
FROM tbl3
GROUP BY CAST(DATEPART(yyyy,DATE1) AS
varchar (5)) + '-' + CAST(DATENAME(m,ec2.DATE2)
AS varchar(3))
ORDER BY [Month]
So in the above query I have results for 2 different years so its sorting year in integer wise but Month according to alphabets(as its DATENAME)
Examples:
2013-Dec 4.45
2013-Nov 5.55
2014-Jan 2.35
2014-Jan 2-85
The problem is I am using DATE2 in my aggregate function(Avg) and hence can't use it in ORDER BY clause.
Anyone has a solution for this problem. I will be really thankful if you can help me. I read other questions regarding this problem but didn't find the solution.
Thanks in advance.
A convoluted way, but works in any situation. Use CTE to solve your issue as below:
With CTE as (
SELECT CAST(DATEPART(yyyy,DATE1)
AS varchar (5)) + '-' + CAST(DATENAME(m,ec2.DATE2)
AS varchar(3)) AS [Month],
CAST(AVG(CAST(DATEDIFF(day,DATE1, DATE2)
AS DECIMAL(10,2))) AS DECIMAL(10,2)) AS tt
FROM tbl3
GROUP BY CAST(DATEPART(yyyy,DATE1) AS
varchar (5)) + '-' + CAST(DATENAME(m,ec2.DATE2)
AS varchar(3))
Select * from CTE
ORDER BY
DATEPART(yyyy, cast([Month] as datetime)),
DATEPART(mm, cast([Month] as datetime));
I agree you can order by Year/Month as Darius X suggested. You can also use a cross apply to "wrap" your calculation. Not sure it would solve your specfic problem, but for additional information. I figure out the MatchStatus in the CROSS APPLY then use MatchStatus in the SELECT & GROUP BY clauses.
SELECT
MatchStatus,
COUNT(*)
FROM MPI.ACTData.Matches
CROSS APPLY (SELECT CASE WHEN MatchScore >= 69 THEN 'Match'
ELSE 'Review' END MatchStatus) ms
GROUP BY MatchStatus

MS SQL distinct function

I have the query below
SELECT distinct
count(patient.id)
CAST(YEAR(completiondate) AS VARCHAR(4)) + '-' + CAST(MONTH(completiondate) AS VARCHAR(2)) AS Mjesec
FROM ....
WHERE
incident.completionDate Between Convert(smalldatetime, '01/10/2007', 103) and Convert(smalldatetime, '01/11/2013', 103)
and servicecharges.serviceid in (47)
and incident.status != 6
and ServiceRequestDescription LIKE 'something'
and chargeDescr = 'test'
group by CAST(YEAR(completiondate) AS VARCHAR(4)) + '-' + CAST(MONTH(completiondate) AS VARCHAR(2))
the result i take, have unique rows of patient.id AND Year-Month. That means that i can have multiple rows with the same patient.id and several year-month.
how can i change that query, in order to take the results, with each patient.id only once, with the first completiondate with the specific elements?
I guess it should be:
SELECT
patient.id
MIN(
CAST(YEAR(completiondate) AS VARCHAR(4)) + '-' + CAST(MONTH(completiondate) AS VARCHAR(2))
)
AS Mjesec
FROM ....
WHERE
incident.completionDate Between Convert(smalldatetime, '01/10/2007', 103) and Convert(smalldatetime, '01/11/2013', 103)
and servicecharges.serviceid in (47)
and incident.status != 6
and ServiceRequestDescription LIKE 'something'
and chargeDescr = 'test'
group by patient.id
Please Try it
WITH CTE AS
(
SELECT *,RN=ROW_NUMBER() OVER (PARTITION BY patient ORDER BY patient DESC) FROM tablename
)
select * from CTE where RN>1