How to remove the column in group by - sql

I am working on a query where I want MG.Actid to appear as a SELECT column but not within a group by because it is not listing the results that I want. The group structure is getting spoiled if I have it in group by. Please let me know how to retain it in select column and remove it from group by.
Want the group by only for SR.Rsrcid, sr.frsntnm, sr.lstm
Query :
SELECT
(SR.LstNm+ ', '+ SR.FrstNm) as 'Employee Name',
MG.Actid as goalid,
SR.Rsrcid as EmpID,
COUNT(Mg.ActID) '# Goals',
SUM(CASE
WHEN PrntActID != '' THEN 1
ELSE 0
END) AS '# Aligned'
FROM TM.SResource AS SR
LEFT OUTER JOIN TM.MatrixGoal AS Mg
ON SR.RsrcID = MG.RsrcID AND MG.DelFlg = 0
WHERE MG.ActiveFlg = 1
GROUP BY SR.RsrcId,SR.LstNm,SR.FrstNm
ORDER BY SR.LstNm,SR.FrstNm

One way to do this is to use the 'partition by' clause in your aggregate functions (like SUM and COUNT), and then select the distinct rows from your data set. Effectively, you move the group by statement to a partition for each aggregate, like this:
SELECT DISTINCT
(SR.LstNm+ ', '+ SR.FrstNm) as 'Employee Name',
MG.Actid as goalid,
SR.Rsrcid as EmpID,
COUNT(Mg.ActID) OVER (PARTITION BY SR.RsrcId,SR.LstNm,SR.FrstNm) '# Goals',
SUM(CASE
WHEN PrntActID != '' THEN 1
ELSE 0
END) OVER (PARTITION BY SR.RsrcId,SR.LstNm,SR.FrstNm) AS '# Aligned'
FROM TM.SResource AS SR
LEFT OUTER JOIN TM.MatrixGoal AS Mg
ON SR.RsrcID = MG.RsrcID AND MG.DelFlg = 0
WHERE MG.ActiveFlg = 1
ORDER BY SR.LstNm,SR.FrstNm

Related

MSSQL: Get percentage of match based on criteria in query

I have a query which searches for duplicates on my database. I am searching based on firstname, lastname, and date of birth. What I want to do is to show some percentage, so if it matches with all three it will show 100%, if it matches with just the firstname and last name, it should say 66% etc.. I am not sure how I can go about this.
I am doing this on Microsoft SQL
Below is my current query:
SELECT DISTINCT t.CUSTID, t.FORENAME, t.SURNAME, t.GENDER, CONVERT(varchar, t.DATE_BIRTH, 103) as
DOB
FROM CUSTOMERS AS t
INNER JOIN (
SELECT FORENAME, SURNAME, DATE_BIRTH
FROM CUSTOMERS
GROUP BY FORENAME, SURNAME, DATE_BIRTH
HAVING COUNT(*) > 1) AS td
ON t.FORENAME = td.FORENAME AND t.SURNAME = td.SURNAME
AND t.DATE_BIRTH = td.DATE_BIRTH
You can use something like this:
select c.*, c2.*,
( (case when c.forename = c2.forename then 1.0 else 0 end) +
(case when c.surname = c2.surname then 1.0 else 0 end) +
(case when c.date_of_birth = c2.date_of_birth then 1.0 else 0 end)
) / 3 as ratio
from customers c join
customers c2
on c.forename = c2.forename or
c.surname = c2.surname or
c.date_of_birth = c2.date_of_birth
order by ratio desc;
This will not be efficient. Also, every customer will be compared to itself so the result set will be large.

Aggregate Function on an Expression Containing A Subquery

With the following t-sql query:
select u.userid
into #temp
from user u
where u.type = 1;
select top 50
contentid,
count(*) as all_views,
sum(case when hc.userid in (select userid from #temp) then 1 else 0 end) as first_count,
sum(case when hc.userid in (40615, 40616) then 1 else 0 end) as another_count
from hitcounts hc
inner join user u on u.userid = hc.userid
group by hc.contentid
order by count(*) desc;
I get an error message
Cannot perform an aggregate function on an expression containing an aggregate or a subquery.
However, if just include the column 'another_count' (with the hard-coded list of identifiers), everything works as I expected. Is there a way I should go about only getting the count for userids contained within a subquery? I plan to have multiple columns, each counting up a set/subquery of different userids.
Performance is not a concern at this point and I appreciate any guidance.
You don't need a temporary table for this purpose. Just use a conditional aggregation:
select top 50 contentid,
count(*) as all_views,
sum(case when u.type = 1 then 1 else 0 end) as first_count,
sum(case when hc.userid in (40615, 40616) then 1 else 0 end) as another_count
from hitcounts hc join
user u
on u.userid = hc.userid
group by hc.contentid
order by count(*) desc;

Apply Pivot on multiple colums and rows

This is my sample table and I want to pivot the Leave column and get max to leave opening, debit and credit value and balance leaves
Formula for Balance Leaves: leaveopen + leavecr - leaveused - leavedb
Below is the expected output
so far I have managed to get leaveopening but not able to get all the values in a single query
select e.Code,e.FName + ' ' + case when e.LName !=null then e.LName else ' ' end [Name],l.*
from .EmployeeDetail e
inner join (select * from(select Leave,LeaveOpen,EmployeeId,CompanyId from LeaveOpening where Leave in ('PL','SL','Coff') and employeeid=534 ) src pivot(max(LeaveOpen) for Leave in (PL,SL,Coff)) as src2) l on e.Id = l.EmployeeId and e.CompanyId = l.CompanyId and employeeid=534
Here is a short example using Case statement instead of Pivot.
select EmployeeId
,MAX(CASE WHEN Leave = 'PL' THEN LeaveOpen ELSE 0 END) AS [PL Opening]
,MAX(CASE WHEN Leave = 'PL' THEN LeaveCredit ELSE 0 END) AS [PL Credit]
from LeaveOpening
group by EmployeeID

How to return 'blank' using Sum function in Sql, if Sum is resulting 0 in SQL

I am using Sql Server 2008. I am adding some column value using Sum function. Like the code below:
SELECT 'RCOAuthorizer LMS',
'' AS Consumer_Loan,
'' AS Auto_Loan,
'' AS Credit_Card,
SUM(CASE
WHEN sq2.loan_type = 'Loan Amendment' THEN sq2.user_count
ELSE ''
END ) AS Loan_Amendment,
SUM(CASE
WHEN sq2.loan_type = 'Pre-Payment' THEN sq2.user_count
ELSE ''
END ) AS Pre_Payment,
SUM(CASE
WHEN sq2.loan_type = 'Corporate Credit card' THEN sq2.user_count
ELSE ''
END ) AS Corporate_Credit_card,
'' AS Auto_Payment_Release,
'' AS Car_Mulkiya
FROM
( SELECT 'RCOAuthorizer' AS ws_name,
'Loan Amendment' AS loan_type,
COUNT (DISTINCT a.bpm_referenceno) AS user_count,
a.user_id AS user_id
FROM BM_LMS_DecisionHistoryGrid a
INNER JOIN
( SELECT m.bpm_referenceno
FROM BM_LMS_EXTTABLE m
WHERE m.request_type = 'Loan Amendment' ) sq1 ON a.bpm_referenceno = sq1.bpm_referenceno
WHERE workstep_name = 'RCOAuthorizer'
GROUP BY a.user_id
UNION SELECT 'RCOAuthorizer',
'Pre-Payment',
COUNT (DISTINCT a.bpm_referenceno), a.user_id
FROM BM_LMS_DecisionHistoryGrid a
INNER JOIN
( SELECT m.bpm_referenceno
FROM BM_LMS_EXTTABLE m
WHERE m.request_type = 'Pre-Payment' ) sq1 ON a.bpm_referenceno = sq1.bpm_referenceno
WHERE workstep_name = 'RCOAuthorizer'
GROUP BY a.user_id
UNION SELECT 'RCOAuthorizer',
'Corporate Credit card',
COUNT (DISTINCT a.bpm_referenceno), a.user_id
FROM BM_LMS_DecisionHistoryGrid a
INNER JOIN
( SELECT m.bpm_referenceno
FROM BM_LMS_EXTTABLE m
WHERE m.request_type = 'Corporate Credit card' ) sq1 ON a.bpm_referenceno = sq1.bpm_referenceno
WHERE workstep_name = 'RCOAuthorizer'
GROUP BY a.user_id ) sq2
GROUP BY sq2.ws_name
The above query will return Sum of all the numbers available in 'a' column. But in case, there is no record, then it will return '0' as result.
I require that if there is no record, it must show blank instead of showing '0'. How to handle the same.
To start, you don't need an ISNULL with a back value of 0 (the neutral for adding) inside a SUM aggregate, as the SUM already ignores NULL values. So SUM(ISNULL(Column, 0)) is equal to SUM(Column) (but different from ISNULL(SUM(Column), 0)!).
Seems that you want a VARCHAR result instead of a numeric one. You can solve this with a CASE.
Select
CASE WHEN Sum(a) = 0 THEN '' ELSE CONVERT(VARCHAR(100), Sum(a)) END
from
table;
If you don't want to repeat the SUM expression:
;WITH SumResult AS
(
Select CONVERT(VARCHAR(100), Sum(a)) AS SumTotal
from table
)
SELECT
CASE WHEN R.SumTotal = '0' THEN '' ELSE R.SumTotal END
FROM
SumResult AS R
Keep in mind that in these both cases, if there is no record to calculate the sum from, the result will be NULL.
EDIT: There is no point in adding '' inside your SUM, as it's converted to 0 to be able to sum. The solution is still the same as I posted before.
Change
SUM(CASE
WHEN sq2.loan_type = 'Pre-Payment' THEN sq2.user_count
ELSE ''
END ) AS Pre_Payment,
for
CASE
WHEN SUM(CASE WHEN sq2.loan_type = 'Pre-Payment' THEN sq2.user_count END) = 0 THEN ''
ELSE CONVERT(VARCHAR(100), SUM(CASE WHEN sq2.loan_type = 'Pre-Payment' THEN sq2.user_count)) END AS Pre_Payment,
Just try this ( use isnull again ):
Select isnull(Sum(isnull(a,0)),0) from table_;
I used table_ instead of table, because table is a reserved keyword.
SQL Fiddle Demo

Sql server aggregate function and GROUP BY Clause error

I have a query below where it compares the number of stagingCabincrew and StagingCockpitCrew columns from the staging schema and compares them to their data schema equivalent 'DataCabinCrew' and 'DataCockpitCrew'.
Below is the query and the results outputted:
WITH CTE AS
(SELECT cd.*,
c.*,
DataFlight,
l.ScheduledDepartureDate,
l.ScheduledDepartureAirport
FROM
(SELECT *,
ROW_NUMBER() OVER(PARTITION BY LegKey
ORDER BY UpdateID DESC) AS RowNumber
FROM Data.Crew) c
INNER JOIN Data.CrewDetail cd ON c.UpdateID = cd.CrewUpdateID
AND cd.IsPassive = 1
AND RowNumber = 1
INNER JOIN
(SELECT *,
Carrier + CAST(FlightNumber AS VARCHAR) + Suffix AS DataFlight
FROM Data.Leg) l ON c.LegKey = l.LegKey )
SELECT StagingFlight,
sac.DepartureDate,
sac.DepartureAirport,
cte.DataFlight,
cte.ScheduledDepartureDate,
cte.ScheduledDepartureAirport,
SUM(CASE
WHEN sac.CREWTYPE = 'F' THEN 1
ELSE 0
END) AS StagingCabinCrew,
SUM(CASE
WHEN sac.CREWTYPE = 'C' THEN 1
ELSE 0
END) AS StagingCockpitCrew,
SUM(CASE
WHEN cte.CrewType = 'F' THEN 1
ELSE 0
END) AS DataCabinCrew,
SUM(CASE
WHEN cte.CrewType = 'C' THEN 1
ELSE 0
END) AS DataCockpitCrew
FROM
(SELECT *,
Airline + CAST(FlightNumber AS VARCHAR) + Suffix AS StagingFlight,
ROW_NUMBER() OVER(PARTITION BY Airline + CAST(FlightNumber AS VARCHAR) + Suffix
ORDER BY UpdateId DESC) AS StageRowNumber
FROM Staging.SabreAssignedCrew) sac
LEFT JOIN CTE cte ON StagingFlight = DataFlight
AND sac.DepartureDate = cte.ScheduledDepartureDate
AND sac.DepartureAirport = cte.ScheduledDepartureAirport
AND sac.CREWTYPE = cte.CrewType
WHERE MONTH(sac.DepartureDate) + YEAR(sac.DepartureDate) = MONTH(GETDATE()) + YEAR(GETDATE())
AND StageRowNumber = 1 --AND cte.ScheduledDepartureDate IS NOT NULL
--AND cte.ScheduledDepartureAirport IS NOT NULL
GROUP BY StagingFlight,
sac.DepartureDate,
sac.DepartureAirport,
cte.DataFlight,
cte.ScheduledDepartureDate,
cte.ScheduledDepartureAirport
The results are correct, all I need to do is add a condition in the WHERE clause where StagingCabinCrew <> DataCabinCrew AND StagingCockpitCrew <> DataCockpitCrew
If a row appears then we have found an error in the data, I just need helping adding this condition in the WHERE Clause because the columns in the WHERE Clause are referring to a SUM and CASE Function. I just need help manipulating the query so that I can add this WHERE Clause
I will guess you are trying to use an alias in the same query.
You CANT do this, because the alias wont be recognized in the WHERE.
SELECT field1 + field2 as myField
FROM yourTable
WHERE myField > 3
You need to include it in a sub query
with cte2 as (
SELECT field1 + field2 as myField
FROM yourTable
)
SELECT *
FROM cte2
WHERE myField > 3
or repeat the function
SELECT field1 + field2 as myField
FROM yourTable
WHERE field1 + field2 > 3