in grouping getting duplicate records - sql-server

I want to filter records on the basis of month. Requirement is in month how much projects are in "completed, pending, started etc" status. This is my query but i am getting duplicate records.
SELECT distinct
convert(varchar(7), w.ExpectedStartDate, 126) AS StatusOfMonth,
COUNT(w.StatusTypeId) AS StatusCount,
w.StatusTypeId,
st.StatusTypeName
FROM Table1 w
LEFT OUTER JOIN StatusType st ON st.StatusTypeId = w.StatusTypeId
WHERE CONVERT(VARCHAR(20), w.ExpectedStartDate, 103) BETWEEN '10/01/2011' AND '14/04/2011'
GROUP BY ExpectedStartDate, w.StatusTypeId, st.StatusTypeName
Please see image to clarify what i want. Please let me know how can i get correct results.

Looks like your grouping by the date, not by the month or by the status of month
Group by
DATEPART(M, ExpectedStartDate)
or
convert(varchar(7), w.ExpectedStartDate, 126)
instead of just ExpectedStartDate
EDIT
In response the comment:
Try getting rid of
convert(varchar(7), w.ExpectedStartDate, 126) AS StatusOfMonth
and just try it like this:
SELECT
convert(varchar, datepart(yyyy, w.ExpectedStartDate)) + '-' + CONVERT(varchar(3), DATENAME(month, w.ExpectedStartDate)),
w.StatusTypeId,
st.StatusTypeName,
COUNT(w.StatusTypeId) AS StatusCount
FROM
Table1 w LEFT OUTER JOIN
StatusType st ON st.StatusTypeId = w.StatusTypeId
WHERE
w.ExpectedStartDate BETWEEN '1/10/2011' AND '04/14/2011'
GROUP BY
datepart(M, w.ExpectedStartDate),
datepart(yyyy, w.ExpectedStartDate),
w.StatusTypeId,
st.StatusTypeName

Related

Update Column using calculation in last year from another table

I am trying to update (using Inner joins for three tables) item stats STAT for table IM_ITEM by highlighting items that sold less than 12 as "D" (Discontinue).
The 2nd table PS_TKT_HIST_LIN has the Quantity sold column QTY_SOLD for each item on each day and the date column BUS_DAT.
I also need a third table IM_INV to filter the data, I need to say the last received date LST_RECV_DAT for these items is earlier than "2019-01-01" and last sales date LST_SAL_DAT is after "2019-01-01". I used the following code
UPDATE M
SET M.STAT = 'D'
FROM
dbo.IM_ITEM AS M
INNER JOIN
IM_INV AS N
ON
M.ITEM_NO = N.ITEM_NO
INNER JOIN
dbo.PS_TKT_HIST_LIN S`
ON
M.ITEM_NO = S.ITEM_NO
WHERE
CONVERT(DATETIME, FLOOR(CONVERT(FLOAT, N.LST_RECV_DAT))) <= '2019-01-01'
AND CONVERT(DATETIME, FLOOR(CONVERT(FLOAT, N.LST_SAL_DAT))) >= '2019-01-01'
AND M.STAT = 'A'
AND SUM(case when DATEPART(YYYY, (BUS_DAT)) = DATEPART(YYYY, DATEADD(YYYY, -1, getdate()))
AND DATEPART(yyyy, (BUS_DAT)) = DATEPART(yyyy, DATEADD(YYYY, -1, getdate()))
then qty_sold else 0)<12
It comes with an error
Any advise please
You should use HAVING clause instead of Sum in where.
You can use CTE to achieve the value, then update accordingly.
;with cte as(
select ITEM_NO, ..
from ..
group by ITEM_NO
having .. < 12
)
update M
set SET M.STAT = 'D'
from dbo.IM_ITEM AS M
inner join cte on M.ITEM_NO = cte.ITEM_NO
You can't use an aggregate function in where clause unless defined under subquery.

Calculate the datediff() between the date 1 and 2

I need to calculate the datediff from one column where the in time marked with a 1 and the out time marked with a 2. if an employee swiped in and there is no out or out but there was no in i would like it to show as null.
I am not sure how I go about doing this.
SELECT
u.userid
,et.name
,CASE
WHEN scs.FullName is NULL THEN u.name
WHEN scs.FullName is NOT NULL THEN scs.FullName
END AS name
,e.LoggedTime AS SwipeTime
,CASE
WHEN et.name = 'Output On By Door' OR et.name = 'User Granted
Entry To Door Using Reading Device' THEN 1
ELSE 2
END AS SwipeTimeDiff
,d.name AS Door
FROM [Users] AS u
LEFT JOIN [Events] AS e ON e.RecordIndex1=u.UserID
LEFT JOIN [EventTypes] AS et on e.EventTypeID = et.EventTypeID
join .[Doors] AS d ON e.RecordIndex2 = d.DoorID
LEFT join SecurityContractorSignIn as scs on scs.Badge = u.lastname
WHERE LoggedTime > CONVERT(DATE, GETDATE()) and d.doorid in (32, 50, 42, 51, 33)
ORDER BY u.name,e.LoggedTime DESC
I would like to have a computed column with the time difference in days, hours and minutes or null if if there is a missing in(1) or out(2) time.
Well, the DATEDIFF() function is fully explained here and the difference for the specific datepart you want to extract is returned as an integer.
According to your need you may do something like but you will have the information in three (or more - if you want to extend) different columns:
-- Calculate the difference of how many days have passed
SELECT DATEDIFF(DAY, LoginTime, LogoutTime) AS DaysPassed
-- Calculate the difference of how many hours have passed
SELECT DATEDIFF(HOUR, LoginTime, LogoutTime) AS HoursPassed
-- Calculate the difference of how minutes have passed
SELECT DATEDIFF(MINUTE, LoginTime, LogoutTime) AS MinutesPassed
If you want to return a string whether the employee logged out or not you may use something like:
SELECT ISNULL(CONVERT(nvarchar(50), DATEDIFF(MONTH, '2019-01-04', NULL)), 'No logout')

Find out Monthly Percentage in SQL

I am trying to find out monthly percentage (last 12 Months) for the below query
with severity wise, it would be great if anyone could help me out
SELECT Month(a.[Work Initated Date]) AS Month, a.[Initial Severity],
(CAST(Count(a.[Case Number]) AS Decimal(10,1))/ (select CAST(Count(a.[Case Number]) AS Decimal(10,1))
FROM [DSTRINING].[dbo].[SFDC WorkInitiated] (nolock) a
where a.[Initial Severity]='Critical' AND Month(a.[Work Initated Date])=Month(getdate()))*100) AS 'Work Initated%'
FROM [DSTRINING].[dbo].[SFDC WorkInitiated] (nolock) a
where a.[Initial Severity]='Critical' AND Month(a.[Work Initated Date])=Month(getdate()) AND a.[Work Initiated Target Breached]='NO'
Group by Month(a.[Work Initated Date]), a.[Initial Severity]
You can use window functions for this. Your query is a bit hard to follow, but . . .
select Year(wi.[Work Initated Date]) AS yyyy, Month(wi.[Work Initated Date]) AS mm,
wi.[Initial Severity],
count(*) * 100.0/ sum(count(*)) over partition by Year(wi.[Work Initated Date]), Month(wi.[Work Initated Date])) as [Work Initated%]
from [DSTRINING].[dbo].[SFDC WorkInitiated] wi
where wi.[Initial Severity] = 'Critical' and
Month(wi.[Work Initated Date]) = Month(getdate())) and
wi.[Work Initiated Target Breached] = 'NO'
Group by Year(wi.[Work Initated Date]), Month(wi.[Work Initated Date]), wi.[Initial Severity];
Notes:
I included the year along with the month. I just think that is a good practice to avoid unwanted errors.
I changed the table alias to the initials of the table. That makes the query easier to follow.
The window function in the select calculates the ratio you want.
I removed the conversion to decimal(10, 1). I think that confuses the query (although you can add it back in for your output purposes).

Why REPLACE query is taking so much time in SQL Server 2008

I Have a SQL query which converts the date time to 106 format and after that I am replacing the blank space to - which takes too much time almost 4 min while executing . Example as follows
REPLACE(CONVERT(VARCHAR,GETDATE(),106),' ','-') DDate
Output 19-Feb-2015
Without replace my query is taking 0 second
Is there any another way to get the custom format dates as mentioned above ?
I understood that REPLACE will compare the collection of result items.
But it should not take 4 min to replace 100 to 200 data.
Any thoughts?
Query as
SELECT TOP(ISNULL(100,'10000'))
FD.Flight 'Select'
,FD.Filename
,ISNULL(FD.RefNo, 'FLT-' + CONVERT(VARCHAR, FD.FLID)) 'FlightID'
,FD.Registration
,ISNULL(FD.FlightNumber, '') FlightNumber
**,REPLACE(CONVERT(VARCHAR,FD.TKD,106),' ','-') TODate**
,FD.TOGMT
**,REPLACE(CONVERT(VARCHAR,FD.LKD,106),' ','-') LDDate**
,FD.LDGMT
,FD.Origin
,FD.Destination
,FD.Pilot
,FD.CoPilot
**,REPLACE(CONVERT(VARCHAR,FD.DumpDate,106),' ','-') DDate**
,FD.UserName
,FD.FlightCount
,FD.AcVariation
FROM
dbo.vw_FlightDetails FD
LEFT JOIN [dbo].FlightRemark RM ON RM.FlightID = FD.FLID
WHERE
1=1
ORDER BY
FD.TKD DESC
,FD.TOGMT DESC
Bold Area is the problem i am facing
It's hard to tell what's happening here, but you can try this:
select <all your _other_ columns>,
ISNULL(x.RefNo, 'FLT-' + CONVERT(VARCHAR, x.FLID)) FlightID,
REPLACE(CONVERT(VARCHAR, x.TKD, 106),' ','-') TODate,
REPLACE(CONVERT(VARCHAR, x.LKD, 106),' ','-') LDDate,
REPLACE(CONVERT(VARCHAR, x.DumpDate, 106),' ','-') DDate,
from (
SELECT TOP (ISNULL(100,'10000'))
FD.Flight 'Select'
,FD.Filename
,FD.RefNo,
,FD.FLID
,FD.Registration
,ISNULL(FD.FlightNumber, '') FlightNumber
,FD.TKD
,FD.TOGMT
,FD.LKD
,FD.LDGMT
,FD.Origin
,FD.Destination
,FD.Pilot
,FD.CoPilot
,FD.DumpDate
,FD.UserName
,FD.FlightCount
,FD.AcVariation
FROM
dbo.vw_FlightDetails FD
LEFT JOIN [dbo].FlightRemark RM ON RM.FlightID = FD.FLID
WHERE
1=1
ORDER BY
FD.TKD DESC
,FD.TOGMT DESC
) x
basically, bury the query into a subquery, then format the dates only on the resulting rows. I suspect this is happening because of the top() statement... it is probably processing many more rows with the REPLACE than it needs to.

how to use convert and datepart at the same time

I have here a select command which is used in my crystal report:
SELECT cfvgl.v_id, operator.o_id, cfvgl.cfvgl_no, operator.owner_name,
operator.business_address, vessel_details.ship_name, payment.or_number ,
payment .date_paid , payment.amount , signature.data,
cfvgl.cfvgl_date_released, DATEPART(day, cfvgl.cfvgl_validity_start) as day_issued,
DATEPART(month, cfvgl.cfvgl_validity_start) as month_issued,
DATEPART(year, cfvgl.cfvgl_validity_start) as year,
gear.bag_bunt_mesh_size, gear.body_mesh_size, gear.wing_mesh_size,
cfvgl.catcher_type, cfvgl.other_gear, gear.stretched_depth,
gear.finished_depth, gear.mesh_size, gear.finished_length,
gear.finished_width, gear.total_length, gear.cod_end_mesh_size,
gear.otter_board_size, gear.towing_rope_length, gear.tomweight,
gear.bouyline_length, gear.branchline_length, gear.branchline_distance,
gear.hook_number, gear.hook_type, gear.hook_size, gear.bait_type,
gear.hook_total_number, gear.target_species, gear.mainline_length,
gear.swivel_size, gear.wire_leader_length, gear.netting_type
FROM cfvgl INNER JOIN
vessel_details ON vessel_details.v_id = cfvgl.v_id INNER JOIN
operator ON vessel_details.o_id = operator.o_id LEFT OUTER JOIN
applications ON vessel_details.v_id = applications.v_id LEFT OUTER JOIN
payment ON payment.app_no = applications.app_no LEFT OUTER JOIN
gear ON gear.v_id = vessel_details.v_id LEFT OUTER JOIN
signature ON signature.signature_id = cfvgl.signature_id
my problem is , i have to convert and display the return date of the datepart(month) as words, for example 1 = january ..
i only datepart the month ,
DATEPART(month, cfvgl.cfvgl_validity_start) as month_issued
how will i able to change the format of the datepart month to words?
thanks.
Use DATENAME to get the name.
DATENAME(month, cfvgl.cfvgl_validity_start) as month_issued
Use the DATENAME function to get the month in words like so:
SELECT DATENAME(month, cfvgl.cfvgl_validity_start) AS month_issued
FROM yourtable

Resources