MS SQL distinct function - sql

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

Related

How to write a loop for such sql query

I need to write such query:
SELECT CAST (date_time_column AS DATE) as 'Date',
AVG(CASE WHEN FORMAT(date_time_column, 'HH:mm') = '00:00' then my_values ELSE NULL end) as '00:00',
........
AVG(CASE WHEN FORMAT(date_time_column, 'HH:mm') = '23:59' then my_values ELSE NULL end) as '23:59'
FROM table
where date_time_column > '2021-08-12'
GROUP BY CAST (date_time_column AS DATE)
What is a way to avoid writing 1440 lines in a query?
Try the below method (Change the variables to match your table and field)
/*Generate all minutes in a day in a string variable*/
Declare #timeRange varchar(max)=null
declare #startdate Datetime='2021-08-12 00:00';
; WITH cte AS
(
SELECT 1 i, #startdate AS resultDate
UNION ALL
SELECT i + 1, DATEADD(minute, i, #startdate )
FROM cte
WHERE DATEADD(minute, i, #startdate ) < DateAdd(day,1,#startdate)
)
SELECT #timeRange=Coalesce(#timeRange +',' + '['+Format(resultDate,'HH:mm')+']','['+Format(resultDate,'HH:mm')+']') FROM cte
OPTION (MAXRECURSION 2000);
/* (Change These variables to match your table & fields */
declare #filterQuery varchar(300)=' where {date_time_column}>''2021-01-01''';
declare #dateTimeColumn varchar(30)='{date_time_column}';
declare #valueColumn varchar(30)='{value_column}';
declare #myTable varchar(20)='{my_table}';
/*Generate Pivot Query */
DECLARE #query AS NVARCHAR(MAX);
set #query= '
SELECT *
FROM (SELECT Cast('+ #dateTimeColumn +' as Date) Resultdate,
       FORMAT(' + #dateTimeColumn + ', ''HH:mm'') DateMinute,
       ' + #valueColumn + ' FROM ' + #myTable + ' ' + #filterQuery +'
     ) FormattedData
PIVOT( AVG('+ #valueColumn + ')  
    FOR DateMinute IN ('+ #timeRange +')
) AS pivotTable
';
/*Execute Generated Query*/
execute(#query)
What you want to do is to return your data in rows, not columns. That is a row for every minute rather than a column for every minute.
Try it something like this:
WITH
cteNums AS
(
Select TOP (1440) ROW_NUMBER() OVER(order by (Select Null)) - 1 as num
From sys.all_columns
Order By num
)
, cteMinutes AS
(
Select FORMAT(CAST(num/cast(1440.0 as real) as DATETIME), N'HH:mm') as Minutes
From cteNums
)
select CAST(t.date_time_column AS DATE) as 'Date',
m.Minutes,
AVG(CASE WHEN FORMAT(t.date_time_column, 'HH:mm') = m.Minute then t.my_values ELSE NULL end) as AvgValues
FROM cteMinutes m
LEFT JOIN [table] t ON m.Minutes = FORMAT(t.date_time_column, 'HH:mm')
where t.date_time_column > '2021-08-12'
GROUP BY CAST(t.date_time_column AS DATE), m.Minutes
ORDER BY CAST(t.date_time_column AS DATE), m.Minutes
;
I cannot, of course, test this as no test data or table definitions were provided.

Need monthly report where I need summation of Qty for each day

I have one table STOCK_REGISTER where I have columns Id, ItmId, Qty, CreatedDate. And there are daily transaction data like item inward, outward and all.
Now I am developing one Monthly Report where I want to display Day wise summation of item qty for whole month. I have written following query to do so.
SELECT CONVERT(Date,CreatedDate) AS CreatedDate,ItmId, SUM(Qty)
FROM STOCK_REGISTER
GROUP BY CONVERT(Date,CreatedDate),ItmId
This query returns correct data but if I am asking for April-2017 data and STOCK_REGISTER don't have any record on 5th April then it's not displaying 5th April at all where I need 0 value in qty for that item in 5th April.
Can you help me out to get this type of data?
Edit :
I have created query which gives all days of any particular month and have applied left join with STOCK_REGISTER, but still not solving my issue.
declare #month int, #year int
set #month = 4
set #year = 2017
SELECT CAST(CAST(#year AS VARCHAR) + '-' + CAST(#Month AS VARCHAR) + '-01' AS DATETIME) + A.Number AS STKFG_CREATED_DATE,
B.STKFG_ITM_ID,
0 AS OPENING_STOCK,
SUM(STKFG_QTY)
FROM master..spt_values A
LEFT JOIN STOCK_REGISTER_FG B
ON CONVERT(DATE,CAST(CAST(#year AS VARCHAR) + '-' + CAST(#Month AS VARCHAR) + '-01' AS DATETIME) + A.Number) = CONVERT(DATE,B.STKFG_CREATED_DATE)
AND C.ITM_ID = B.STKFG_ITM_ID
WHERE type = 'P'
AND (CAST(CAST(#year AS VARCHAR) + '-' + CAST(#Month AS VARCHAR) + '-01' AS DATETIME) + A.Number ) <
DATEADD(mm,1,CAST(CAST(#year AS VARCHAR) + '-' + CAST(#Month AS VARCHAR) + '-01' AS DATETIME) )
AND STKFG_TRAT_ID = 6
GROUP BY A.Number, B.STKFG_ITM_ID
ORDER BY B.STKFG_ITM_ID,CAST(CAST(#year AS VARCHAR) + '-' + CAST(#Month AS VARCHAR) + '-01' AS DATETIME) + A.Number
Thank you for your comments.
I have found one solution which works fine for me.
Here #TEMP_TABLE contains all dates.
SELECT A.CREATED_DATE,B.ITM_NAME,ISNULL(C.STKFG_QTY,0)
FROM #TEMP_TABLE A
CROSS APPLY ITEM_MASTER B
LEFT JOIN ( SELECT CONVERT(DATE,STKFG_CREATED_DATE) AS STKFG_CREATED_DATE, STKFG_ITM_ID, SUM(STKFG_QTY) AS STKFG_QTY
FROM STOCK_REGISTER_FG GROUP BY CONVERT(DATE,STKFG_CREATED_DATE),STKFG_ITM_ID) C
ON CONVERT(DATE,A.CREATED_DATE) = CONVERT(DATE,C.STKFG_CREATED_DATE)
AND B.ITM_ID = C.STKFG_ITM_ID
ORDER BY B.ITM_NAME,A.CREATED_DATE
Try below script. Here #tblData is your actual table name.
declare #tblData table
(id int,datecolumn date)
INSERT INTO #tblData
(id,datecolumn)
SELECT 1,'2010-01-01' UNION ALL
SELECT 3,'2010-01-01' UNION ALL
SELECT 1,'2010-01-03' UNION ALL
SELECT 2,'2010-01-04' UNION ALL
SELECT 1,'2010-01-05' UNION ALL
SELECT 3,'2010-01-06' UNION ALL
SELECT 1,'2010-01-10' UNION ALL
SELECT 1,'2010-01-10' UNION ALL
SELECT 2,'2010-01-11' UNION ALL
SELECT 1,'2010-01-11' UNION ALL
SELECT 2,'2010-01-11' UNION ALL
SELECT 1,'2010-01-12' UNION ALL
SELECT 3,'2010-01-13'
DECLARE #MaxDate DATE,
#MinDate DATE,
#iDate DATE
DECLARE #DateSequence TABLE(
DATE1 DATE
)
SELECT #MaxDate = Convert(DATE,Max(datecolumn)),
#MinDate = Convert(DATE,Min(datecolumn))
FROM #tblData -- Put your month condition
SET #iDate = #MinDate
WHILE (#iDate <= #MaxDate)
BEGIN
INSERT #DateSequence
SELECT #iDate
SET #iDate = Convert(DATE,Dateadd(DAY,1,#iDate))
END
SELECT a.DATE1 ,isnull(sum(b.id),0) as total
FROM #DateSequence a left join #tblData b on a.DATE1=b.datecolumn
group by a.DATE1
Thanks,

SQL Server : duplicate counts

I have the following. But in the final result some of the employee ID's are counted twice. My goal is to only count distinct employeeID for the [UniqueEmployees] column... Can someone please help me?
This is the code here:
IF OBJECT_ID(N'tempdb..#GG') IS NOT NULL
DROP TABLE #GG
SELECT DISTINCT
[month], vv.Hiremonth,
LoanNumber, vv.EmployeeId,
agentname,
vv.YearsOfService, vv.MonthsofService,
vv.TenureGrouping, vv.TenureMonthGrouping,
manager,
SUM([Call Counts]) as Calls,
SUM(opportunities) as Opportunities,
SUM([Discussed w/Customer]) as [Discussed w/Customer],
SUM(DidNotDiscuss) as [DidNotDiscuss],
SUM(CustomerInterested) as CustomerInterested,
(SELECT COUNT(DISTINCT MGR.EmployeeId)
FROM #MANAGERS MGR
WHERE --EmployeeId = EmployeeId
--and
CAST(CONVERT(datetime, RIGHT(MGR.HireMonth, 4) + LEFT(MGR.HireMonth, 2) + '01') as DATE) <= CAST(CONVERT(datetime, right([Month], 4) + left([Month], 2) + '01') as DATE)
--and MonthsOfService = MonthsOfService
--and YearsOfService = YearsOfService
) as UniqueEmployees
INTO
#GG
FROM
#FINALtemp2b VV
--left join
--(select distinct Employeeid
--from #FINALtemp2b) CC
--on CC.EmployeeId = VV.EmployeeId
GROUP BY
[month], vv.Hiremonth, LoanNumber, vv.EmployeeId,
agentname, vv.YearsOfService, vv.MonthsofService,
vv.TenureGrouping, vv.TenureMonthGrouping, manager
ORDER BY
[month]
Try removing the first 'distinct' and the excess 'select'.
IF OBJECT_ID(N'tempdb..#GG') is not null Drop Table #GG
select *
into #GG
from (
select
[month],
vv.Hiremonth,
LoanNumber,
vv.EmployeeId,
agentname,
vv.YearsOfService,
vv.MonthsofService,
vv.TenureGrouping,
vv.TenureMonthGrouping,
manager,
SUM([Call Counts]) as Calls,
sum(opportunities) as Opportunities,
sum([Discussed w/Customer]) as [Discussed w/Customer],
sum(DidNotDiscuss) as [DidNotDiscuss],
sum(CustomerInterested) as CustomerInterested,
count(distinct (MGR.EmployeeId))
from #MANAGERS MGR
where cast(convert(datetime,right(MGR.HireMonth,4) + left(MGR.HireMonth,2) + '01') as DATE) <= cast(convert(datetime,right([Month],4) + left([Month],2) + '01') as DATE)
group by
[month],
vv.Hiremonth,
LoanNumber,
vv.EmployeeId,
agentname,
vv.YearsOfService,
vv.MonthsofService,
vv.TenureGrouping,
vv.TenureMonthGrouping,
manager
) as UniqueEmployees

Sum by month in 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)

sql : calculate the total birthday moth based on month

I want to code a query to calculate the total birthday moth based on month . Here is the sample data . Two person's bithday are April, 1980 .
How to write this query ?
John 02/21/1980
Peter 02/22/1980
Lucy 04/21/1980
------ result -----
01/1980 0
02/1980 2
03/1980 0
04/1980 1
05/1980 0
.....
You can loop for every months like this:
DECLARE #month INT
DECLARE #year INT
DECLARE #result TABLE (MonthYear varchar(7),BirthdaysCount INT)
SET #month = 1
SET #year = 1980
WHILE(#month < 13)
BEGIN
INSERT INTO #result
SELECT (CAST(#month as VARCHAR) + '/' + CAST(#year as VARCHAR)),
COUNT(*)
FROM test
WHERE MONTH(birth) = #month AND YEAR(birth) = #year
SET #month = #month + 1
END
select * from #result
See the fiddle: http://sqlfiddle.com/#!3/20692/2
In MySQL you would do this:
select concat(month(dob), '/', year(dob)) monthYear, count(*) cnt from t
group by monthYear
order by year(dob), month(dob)
However, in order to get the "missing dates" you'll have to generate data, because 01/1980 is not in any table, as far as I can see. Check this answer to see how.
how about this for sql-server
create table #temp
(
name varchar(50),
DOB datetime
)
insert into #temp values ('john', '2/21/1980')
insert into #temp values ('peter', '2/22/1980')
insert into #temp values ('lucy', '4/21/1980')
select convert(varchar(2), MONTH(DOB)) + '/' + Convert(varchar(4), YEAR(DOB)) as [MM/YYYY]
, count(*) as TotalCount
from #temp
group by convert(varchar(2), MONTH(DOB)) + '/' + Convert(varchar(4), YEAR(DOB))
drop table #temp
EDIT - This will get you all records for the dates included in the dates in the table. It will use the Min/Max Date in the table to get the date range, you then use this range to get the count of the birthdays in each month:
create table #temp
(
name varchar(50),
DOB datetime
)
insert into #temp values ('john', '2/21/1980')
insert into #temp values ('peter', '2/22/1980')
insert into #temp values ('lucy', '4/21/1980')
;with cte as
(
select min(DOB) as MinDate, max(DOB) as MaxDate
from #temp
union all
SELECT dateadd(mm, 1, t.MinDate), t.MaxDate
from cte t
where dateadd(mm, 1, t.MinDate) <= t.MaxDate
)
select convert(varchar(2), MONTH(c.MinDate)) + '/' + Convert(varchar(4), YEAR(c.MinDate))
, IsNull(t.TotalCount, 0) as TotalCount
from cte c
LEFT JOIN
(
SELECT convert(varchar(2), MONTH(DOB)) + '/' + Convert(varchar(4), YEAR(DOB)) as [MM/YYYY]
, count(*) as TotalCount
FROM #temp
group by convert(varchar(2), MONTH(DOB)) + '/' + Convert(varchar(4), YEAR(DOB))
) t
on convert(varchar(2), MONTH(C.MinDate)) + '/' + Convert(varchar(4), YEAR(C.MinDate))
= t.[MM/YYYY]
drop table #temp