Using Case statement inside Join Condition - sql

How can I achieve this? I am getting an error incorrect syntax near between
#STARTDATE, #ENDDATE, #CREATEDDATE -- INPUT PARAMETERS
SELECT *
FROM [DBO].[xxx] x
INNER JOIN [DBO].[yyy] y
ON x.ID = y.ID
AND CASE WHEN #CREATEDDATE = 1
THEN x.CreatedDate BETWEEN #STARTDATE AND #ENDDATE
WHEN #CREATEDDATE = 0
THEN x.ClosedDate BETWEEN #STARTDATE AND #ENDDATE

SQL Server does not treat boolean expressions as something that a case expression can return. In fact, case in on and where clauses is to be discouraged. And you can easily express this using more basic boolean operations:
SELECT *
FROM [DBO].[xxx] x INNER JOIN
[DBO].[yyy] y
ON x.ID = y.ID AND
( (#CREATEDDATE = 1 AND x.CreatedDate BETWEEN #STARTDATE AND #ENDDATE) OR
(#CREATEDDATE = 0 AND x.ClosedDate BETWEEN #STARTDATE AND #ENDDATE)
)

You can try the following query
SELECT *
FROM [DBO].[xxx] x
INNER JOIN [DBO].[yyy] y
ON x.ID = y.ID
AND CASE WHEN #CREATEDDATE = 1 AND x.CreatedDate BETWEEN #STARTDATE AND #ENDDATE THEN 1
WHEN #CREATEDDATE = 0 AND x.ClosedDate BETWEEN #STARTDATE AND #ENDDATE THEN 1
ELSE 0 END = 1

Related

Skip a WHERE condition if a #variable is empty

In the below code I don't want the second part of the join condition to be applicable if #selectAll = 1
(ie and (listMap.dateOfTask between #startDate and #endDate)
I am using SQL Server.
#userId nvarchar(200),
#startDate nvarchar(200),
#endDate nvarchar(200),
#selectAll bit
select
*
from tmListMap l
right join tmTime t
on
l.timeId = t.timeId
and (l.dateOfTask between #startDate and #endDate) //Don’t need this condition if #selectAll = 1
#Damien suggested you need a or condition like
#userId nvarchar(200),
#startDate nvarchar(200),
#endDate nvarchar(200),
#selectAll bit
select
*
from tmListMap l
right join tmTime t
on
l.timeId = t.timeId
and ((l.dateOfTask between #startDate and #endDate) or #selectAll=1)
#userId nvarchar(200),
#startDate nvarchar(200),
#endDate nvarchar(200),
#selectAll bit
select
*
from tmListMap l
right join tmTime t
on
l.timeId = t.timeId
where #selectAll = 1 or (l.dateOfTask between #startDate and #endDate)
Two options.
Option A as OR clause
#startDate date,
#endDate date,
#selectAll bit
select
*
from tmListMap l
right join tmTime t
on l.timeId = t.timeId
WHERE
(
l.dateOfTask between #startDate and #endDate and #selectAll = 0
OR
#selectAll = 1
)
Option B as UNION ALL
#startDate date,
#endDate date,
#selectAll bit
select
*
from tmListMap l
right join tmTime t
on l.timeId = t.timeId
WHERE #selectAll = 0
and l.dateOfTask between #startDate and #endDate
UNION ALL
select
*
from tmListMap l
right join tmTime t
on l.timeId = t.timeId
WHERE #selectAll = 1
Depends a bit on your data which will be faster. In my experience the UNION ALL scales better. As long as the different parts are absolutely not able to create duplicates.

Sql joins returning Null Results and not accepting conditions

I have 4 tables that I am trying to get data from yet my join statement returns null. I have tried full, left and right joins with no success. Below I have provided my code and the diagram, the table that returns null values is the ChannelData table. I am trying to sum the Vvalue from this table, when i add the condition that i commented out below i.e.between start and end date` my query return no results. I know there must be a problem with my joins but I have tried everything. This table is not normalized properly and I have to use it as is:
DECLARE #bp varchar(4)
DECLARE #priority varchar(2)
DECLARE #startDate datetime
DECLARE #endDate datetime
SET #bp = 1710
SET #priority = 2
SET #endDate = (SELECT EndDate FROM BillingPeriod WHERE BillingPeriodClass_ID = 1 AND CODE = #BP)
SET #startDate = (SELECT EndDate FROM BillingPeriod WHERE BillingPeriodClass_ID = 1 AND CODE = #BP -1 )
SET #startDate = dateadd(minute, 1, #startDate)
SELECT CGS.Description, SUM(CD.Vvalue) AS P_Val, COUNT(CD.VValue) AS P_Rec, DI.Margin
FROM CGS AS CGS
FULL JOIN ChannelParameter AS CP ON CP.ID = CGS.ID
FULL JOIN ChannelData AS CD ON CP.ID = CD.ID
FULL JOIN DataIntegrity AS DI ON DI.CGS_ID_1 = CGS.ID OR DI.CGS_ID_2 = CGS.ID
WHERE --CD.DDate BETWEEN #startDate AND #endDate AND
DI.Priority = #priority
group by CGS.Description, DI.Margin
Click this for Query Result
Please see below:
Channel Data Table
Channel Parameter Table
I have attached pictures as links: also here is what i mean by the table not being normalised properly they both have CGS.ID as a primrary and foreign key but this is actually a primary key in the cgs table the problem is when i try and join the DI table i dont get results from all tables:
DECLARE #bp varchar(4)
DECLARE #priority varchar(2)
DECLARE #startDate datetime
DECLARE #endDate datetime
SET #bp = 1710
SET #priority = 2
SET #endDate = (SELECT EndDate FROM BillingPeriod WHERE BillingPeriodClass_ID = 1 AND CODE = #BP)
SET #startDate = (SELECT EndDate FROM BillingPeriod WHERE BillingPeriodClass_ID = 1 AND CODE = #BP -1 )
SET #startDate = dateadd(minute, 1, #startDate)
SELECT CGS.Description, SUM(CD.Vvalue) AS P_Val, COUNT(CD.VValue) AS P_Rec
FROM CGS AS CGS
FULL JOIN ChannelParameter AS CP ON CP.ID = CGS.ID
FULL JOIN ChannelData AS CD ON CP.ID = CD.ID
WHERE CD.DDate BETWEEN #startDate AND #endDate and CGS.ID = 88
group by CGS.Description
RESULT :
Description P_Val P_Rec
EP 308 12 CONTROL TRF FEEDER NO 1 - Q Exp, 4514.37, 1488
The problem is pretty clear that there is no matched record for CD.DDate BETWEEN #startDate AND #endDate condition. And I suspected that #startDate variable might be null because of returning no record for CODE = #BP -1 condition. So, would you try to change this line;
SET #startDate = (SELECT top 1 EndDate FROM BillingPeriod
WHERE BillingPeriodClass_ID = 1 AND CODE < #BP order by CODE desc)

Which query will be better in terms of perfomance SQL server

I have written two queries and I need help to know which one will be better in term of performance. Both do the same thing. Please also advise if you have better a way of writing the query
Query 1
DECLARE #TotalAvailedLateNightGeneral INT
;WITH CTE (TotalDaysAppliedFor) AS (
SELECT SUM(TotalDaysAppliedFor) AS TotalDaysAppliedFor
FROM [CURFEW_RLX_REQUEST] WITH (NOLOCK)
GROUP BY StaffSeqId, RequestTypeId, MONTH(PermissionRequiredFrom), StatusId, IsActive
HAVING StaffSeqId = 41130
AND RequestTypeId = 3
AND MONTH(PermissionRequiredFrom) = MONTH('2016-03-30 00:00:00.000')
AND StatusId <> 111
AND IsActive = 1
)
SELECT #TotalAvailedLateNightGeneral = SUM(TotalDaysAppliedFor)
FROM CTE
SELECT #TotalAvailedLateNightGeneral
QUERY 2
SELECT SUM(TotalDaysAppliedFor) AS TotalDaysAppliedFor
FROM [CURFEW_RLX_REQUEST] WITH (NOLOCK)
--GROUP BY StaffSeqId,RequestTypeId,MONTH(PermissionRequiredFrom),StatusId,IsActive
WHERE StaffSeqId = 41130
AND RequestTypeId = 3
AND MONTH(PermissionRequiredFrom) = MONTH('2016-03-30 00:00:00.000')
AND StatusId <> 111
AND IsActive = 1
DECLARE #StartDate DATETIME = '2016-03-01'
DECLARE #EndDate DATETIME = '2016-04-01'
SELECT TotalDaysAppliedFor = SUM(TotalDaysAppliedFor)
FROM dbo.QAG_GEMS_CURFEW_RLX_REQUEST
WHERE StaffSeqId = 41130
AND RequestTypeId = 3
AND PermissionRequiredFrom >= #StartDate
AND PermissionRequiredFrom < #EndDate
AND StatusId != 111
AND IsActive = 1

Can we merge 2 SQL with same logic with just marginally difference?

I have 2 SQLs,
SELECT #AlreadyPerformedActionsPerDay = COUNT(*)
FROM UserRewardActions URA
INNER JOIN UserRewardActionTypes URAT ON URAT.ID = URA.UserRewardActionTypeID
WHERE URA.UserID = #UserID
AND (
#UserRewardActionTypeID = 1 -- Because the register action is not per-date-wise(only allows once in lifetime)
OR CreationDateInUtc BETWEEN CAST(GETUTCDATE() AS DATE) AND DATEADD(DAY, 1, CAST(GETUTCDATE() AS DATE)) -- Inside Current Date
);
SELECT #AlreadyRedeemedTheCurrentAction = 1
FROM UserRewardActions URA
INNER JOIN UserRewardActionTypes URAT ON URAT.ID = URA.UserRewardActionTypeID
WHERE URA.UserID = #UserID
AND CreationDateInUtc BETWEEN CAST(GETUTCDATE() AS DATE) AND DATEADD(DAY, 1, CAST(GETUTCDATE() AS DATE)) -- Inside Current Date
AND URL IS NOT NULL
AND URL = #Url;
The fist SQL is the grabbing total number of user actions today. Second, is checking whether the current url is already used by the same user. This is fine. But I am looking to merge this query for performance issue.
well, after reformatting your queries as below. I can see that they have different criteria.
DECLARE #from DateTime;
DECLARE #to DateTime;
SET #from = cast(getutcdate() as Date);
SET #to = dateadd(DAY, 1, #from));
SELECT
#AlreadyPerformedActionsPerDay = COUNT(*)
FROM
UserRewardActions URA
JOIN
UserRewardActionTypes URAT
ON URAT.ID = URA.UserRewardActionTypeID
WHERE
URA.UserID = #UserID
AND
(
#UserRewardActionTypeID = 1
OR
CreationDateInUtc BETWEEN #from AND #to
);
SELECT
#AlreadyRedeemedTheCurrentAction = 1
FROM
UserRewardActions URA
JOIN
UserRewardActionTypes URAT
ON URAT.ID = URA.UserRewardActionTypeID
WHERE
URA.UserID = #UserID
AND
CreationDateInUtc BETWEEN #from AND #to
AND
URL IS NOT NULL
AND
URL = #Url;

Remove subquery from JOIN?

In the following query, I would like the remove the subquery from the JOIN statement (since my two SELECT statements are selecting data from same table). How can I use that alias? Thanks in advance for any help.
declare #StartDate datetime= '8/01/2011'
declare #EndDate datetime = '9/20/2011'
declare #PortfolioId int = 6
SELECT
Previous.PreviousNAV,
Todays.TodaysNAV,
ISNULL((Todays.TodaysNAV-Previous.PreviousNAV),0) NetChange,
ISNULL((Todays.TodaysNAV-Previous.PreviousNAV) / Todays.TodaysNAV,0) BAMLIndex
FROM
(
SELECT PortfolioId,ISNULL(NAV,0) PreviousNAV
FROM Fireball..NAV
WHERE Date BETWEEN #StartDate AND #EndDate and PortfolioId = #PortfolioId
) Previous
JOIN
(
SELECT PortfolioId,ISNULL(NAV,0) TodaysNAV
FROM Fireball..NAV
WHERE Date = #EndDate and PortfolioId = #PortfolioId
) Todays
ON Previous.PortfolioId = Todays.PortfolioId
Just eliminate the subqueries entirely. I don't think they add anything to the query. Try this instead:
SELECT
Previous.NAV as PreviousNAV,
Todays.NAV as TodaysNav,
ISNULL((Todays.NAV-Previous.NAV),0) NetChange,
ISNULL((Todays.NAV-Previous.NAV) / Todays.NAV,0) BAMLIndex
FROM
Fireball..NAV as Previous
JOIN
Fireball..NAV as Todays
ON Previous.portfolioID = Todays.PortfolioID
WHERE Previous.Date BETWEEN #StartDate AND #EndDate
AND Previous.PortfolioId = #PortfolioId
AND Todays.Date = #EndDate