How to use CASE in WHERE clause - tsql

select
SUBSTRING(ackey,1,2) + '-' + SUBSTRING(ackey, 3,3) + '-' + SUBSTRING(ackey,8,6)
from
tHE_Move
where case
when acDocType in ('1900', '1910', '1920', '1930') then acWayOfSale <> 'E'
when acDocType in ('1950', '1960') then acWayOfSale <> 'U'
Can I do something like this?
I solved this with:
select
SUBSTRING(ackey,1,2) + '-' + SUBSTRING(ackey, 3,3) + '-' + SUBSTRING(ackey,8,6)
from
tHE_Move
where
(case when acDocType in ('1900', '1910', '1920', '1930') then acWayOfSale end <> 'E'
or
case when acDocType in ('1950','1960') then acWayOfSale end <> 'U')
But I'm interested if this can be solved in only one case?

You could:
where acWayOfSale <> case when acDocType in ('1900', '1910', '1920', '1930') then 'E'
when acDocType in ('1950', '1960') then 'U'
else ...
end
(Or of course create/modify a table with the acDocType values and the desired character and JOIN to it)

You're on the right track, but CASE returns an expression and in tsql cannot return a boolean.. What you really want to do is use a combination of AND and OR. In your case:
where (acDocType in ('1900', '1910', '1920', '1930') and acWayOfSale <> 'E')
or (acDocType in ('1950','1960') and acWayOfSale <> 'U')

Related

How to fix Incorrect syntax near '=' error in stored procedure that uses dynamic SQL

I attempted to add some additional columns to an existing stored procedure. This entailed not only adding the columns but also creating a LEFT JOIN subquery to gather the additional columns that is commented on " Addition of Sales and Warranties totals". Now, when I execute this code within my stored procedure, I'm getting an error in the SQL command.
I've tried opening a new query window and trying to recreate the query in the proper format to execute it, but I get the following errors: Msg 102, Level 15, State 1, Line 60
Incorrect syntax near ' + case when isnull(#TaxHeaders,') = ' then '.
Msg 102, Level 15, State 1, Line 117
Incorrect syntax near ' + case when isnull(#TaxHeaders,') = ' then '.
I've also tried changing the location of my LEFT JOIN query (SWT,GT) above the T and T1 LEFT JOIN that includes the pivot.
CREATE Procedure [GP].[spInvoiceReprintsSummary]
#CompanyKey varchar(2)=5,
#ParentCustomerNum varchar(255)='BCAA01', --'AAANYCITY', --'AAANPENN01', --'CAAQUEBE01', --'BCAA01', --'CAAQUEBE01',
#StartDateKey varchar(8)=20130306,
#EndDateKey varchar(8)=20130315,
#TaxHeaders varchar(255)='HST,GST,PST,QST' --'GST, QST'
As
Begin
Declare #SQL as varchar(max)
Set #SQL = '
Select S.CompanyKey, S.TaxScheduleID, S.CustomerKey, S.ParentCustomerNum, S.StationID, S.CustomerName, S.DocumentTypeKey, S.DocumentNum, Case When Left(S.DocumentNum, 2)=''ST'' Then 0 ELSE 1 End As EligibleDiscount,S.ExtendedPrice,S.PurchaseOrderNum, DocumentDate, S.TaxAmount, SWT.SalesTotal, SWT.WarrantiesTotal, S.TerritoryId ' + case when isnull(#TaxHeaders,'') = '' then '' else ',' + #TaxHeaders end + ' From
(
--Get distinct documents
Select --Top 100
SD.CompanyKey, SD.TaxScheduleID, CS.CustomerKey, CS.ParentCustomerNum, CS.StationID, CS.CustomerName, SD.DocumentTypeKey, SD.DocumentNum,SD.PurchaseOrderNum, convert(datetime,convert(varchar, DateKey, 112)) As DocumentDate,sum(SD.TaxAmount) as TaxAmount, sum(SD.ExtendedPrice) As ExtendedPrice, CS.TerritoryId From GP.SalesDetail SD
Inner Join GP.Customers CS
on SD.CustomerKey = CS.CustomerKey
Where CS.ParentCustomerNum= ''' + #ParentCustomerNum + ''' And SD.DateKey Between ' + #StartDateKey + ' and ' + #EndDateKey + ' And SD.CompanyKey = ' + #CompanyKey + ' And SD.PostStatus = 1 And SD.VoidStatus = 0
Group by SD.CompanyKey, SD.TaxScheduleID, CS.CustomerKey, CS.ParentCustomerNum, CS.StationID, CS.CustomerName, SD.DocumentTypeKey, SD.DocumentNum,SD.PurchaseOrderNum, convert(datetime,convert(varchar, DateKey, 112)), CS.TerritoryId
--Order By SD.PurchaseOrderNum, SD.DocumentTypeKey
) S
---Addition of sales and warranties totals
LEFT JOIN(
SELECT CASE WHEN GroupName = ''SALES'' then sum(QuantitySold) else 0 end as SalesTotal,CASE WHEN GroupName = ''WARRANTIES'' then sum(QuantitySold) else 0 end as WarrantiesTotal, DocumentNum, CompanyKey FROM
(SELECT
SD.QuantitySold , DocumentNum , SD.CompanyKey
,CASE WHEN I.userDefItemClass1 = ''BATTERY/RETURN'' AND SD.QuantitySold >= 0 THEN ''SALES''
WHEN I.userDefItemClass1 = ''BATTERY/RETURN'' AND SD.QuantitySold < 0 THEN ''RETURNS''
WHEN I.ItemNum = ''RESTOCKING FEE'' AND sd.ExtendedPrice >= 0 THEN ''RETURNS''
WHEN I.ItemNum = ''RESTOCKING FEE'' AND sd.ExtendedPrice < 0 THEN ''SALES''
WHEN I.userDefItemClass1 = ''WARRANTY'' THEN ''WARRANTIES''
WHEN I.userDefItemClass1 = ''NRF'' THEN ''RECYCLING FEES''
WHEN I.userDefItemClass1 = ''CORES'' THEN ''SPENT BATTERIES''
WHEN I.ItemNum IN (''PU2'',''PU4.3'') AND sd.ExtendedPrice > 0 THEN ''RETURNS''
WHEN I.ItemNum IN (''PU2'',''PU4.3'') AND sd.ExtendedPrice < 0 THEN ''SALES''
ELSE ''OTHER'' END AS GroupName
FROM GP.SalesDetail AS SD
INNER JOIN GP.Items AS I ON SD.ItemKey = I.ItemKey
Inner Join GP.Customers CS on SD.CustomerKey = CS.CustomerKey
WHERE
CS.ParentCustomerNum= '' + #ParentCustomerNum + '' And SD.DateKey Between ' + #StartDateKey + ' and ' + #EndDateKey + ' And SD.CompanyKey = ' + #CompanyKey + ' And SD.PostStatus = 1 And SD.VoidStatus = 0
) GN
GROUP BY DocumentNum, GroupName, CompanyKey
) SWT
ON S.Companykey = SWT.CompanyKey And S.DocumentNum = SWT.DocumentNum
Left join (
--Pivot the Tax Types
Select Companykey, DocumentTypeKey, DocumentNum ' + case when isnull(#TaxHeaders,'') = '' then '' else ',' + #TaxHeaders end + ' From (
SELECT SD.CompanyKey,TD.DocumentTypeKey, TD.DocumentNum, TS.TaxDetailLabel, SUM(TD.TaxAmount) AS TaxAmount
FROM GP.TaxSchedules AS TS INNER JOIN
(SELECT SD.CompanyKey, SD.TaxScheduleId, SD.DocumentTypeKey, SD.DocumentNum
FROM GP.SalesDetail SD
Inner Join GP.Customers CS
on SD.CustomerKey = CS.CustomerKey
Where CS.ParentCustomerNum= ''' + #ParentCustomerNum + ''' And SD.DateKey Between ' + #StartDateKey + ' and ' + #EndDateKey + ' And SD.CompanyKey = ' + #CompanyKey + ' And SD.PostStatus = 1 And SD.VoidStatus = 0
GROUP BY SD.CompanyKey, SD.TaxScheduleId, SD.DocumentTypeKey, SD.DocumentNum) AS SD
ON TS.CompanyKey = SD.CompanyKey AND TS.TaxScheduleId = SD.TaxScheduleId
INNER JOIN GP.TaxDetails AS TD ON TD.DocumentNum = SD.DocumentNum AND TD.DocumentTypeKey = SD.DocumentTypeKey AND
TD.LineItemSequenceNum = 0 AND TD.TaxDetailID = TS.TaxDetailId AND TD.CompanyKey = TS.CompanyKey
GROUP BY SD.CompanyKey,TD.DocumentTypeKey,TD.DocumentNum, TS.TaxDetailLabel
) T
Pivot (sum(TaxAmount) For TaxDetailLabel In (' + case when isnull(#TaxHeaders,'') = '' then 'Tax' else #TaxHeaders end + ')) as PVT
) T1
on S.Companykey = T1.CompanyKey And S.DocumentTypeKey = T1.DocumentTypeKey And S.DocumentNum = T1.DocumentNum'
--print #SQL
Exec (#SQL)
End
I expect an output of the original result set including the new columns for SalesTotal and WarrantiesTotal
Replace
CASE
WHEN isnull(#taxheaders,'') = ''
then ''
ELSE ',' + #taxheaders
END
with
CASE
WHEN #taxheaders IS NULL
THEN ''
ELSE ',' + #taxheaders
This should fix the error. Thanks..

Extract string of dynamic length when the indicator of completion exists in multiple instances. Postgres

So if I have a varchar length string column let's call ID(samples below):
97.128.39.256.1460854333288493
25.365.49.12.13454154815132
346.45.156.354.1523425161233
I want to grab, like a left in excel, everything to the left of the 4th period. How do i create a dynamic string to find the fourth instance of a period?
I know substring is a start but not sure how to write in the dynmic length that exists
This is probably the easiest for someone else to read:
select split_part(i, '.', 1) || '.' ||
split_part(i, '.', 2) || '.' ||
split_part(i, '.', 3) || '.' ||
split_part(i, '.', 4)
from (select '97.128.39.256.1460854333288493' as i) as sub;
Or if you don't like split_part and prefer to use arrays:
select array_to_string((string_to_array(i, '.'))[1:4], '.')
from (select '97.128.39.256.1460854333288493' as i) as sub;
I think the array example is a bit harder to grasp at first glance but both work.
Updated answer based on revised question to also convert the Unix timestamp to a Greenplum timestamp:
select 'epoch'::timestamp + '1 second'::interval *
(split_part(i, '.', 5)::numeric/1000000) as event_time,
array_to_string((string_to_array(i, '.'))[1:4], '.') as ip_address
from (
select '97.128.39.256.1460854333288493' as i
) as sub;
You could also try this:
mydb=> select regexp_replace('97.128.39.256.1460854333288493', E'^((?:\\d+\\.){3}\\d+).+$', E'\\1');
regexp_replace
----------------
97.128.39.256
(1 row)
Time: 0.634 ms
with t (s) as ( values
('97.128.39.256.1460854333288493'),
('25.365.49.12.13454154815132'),
('346.45.156.354.1523425161233')
)
select a[1] || '.' || a[2] || '.' || a[3] || '.' || a[4]
from (
select regexp_split_to_array(s, '\.')
from t
) t (a)
;
?column?
----------------
97.128.39.256
25.365.49.12
346.45.156.354

how t use start with -connect by nocycle in postgresql

SELECT coalesce(RPAD('IN',16,' ') || RPAD( M.CASETYPE||'/' || M.CASENUMBER || '/' || M.CASEYEAR,16, ' '),' ') as inmatter
FROM (
select level as LEV, l1.LINKCASECCIN as CCI ,l1.linkcategorycode as lcode
from hclive.LINKEDMATTERS l1
start with l1.MAINCASECCIN ='001003201400100' and l1.linkcategorycode='I'
connect by nocycle prior l1.LINKCASECCIN = l1.MAINCASECCIN and l1.linkcategorycode = 'I'
) s1,
hclive.MAIN M
where M.CCIN=CCI
connect by is done with a recursive common table expression in Postgres.
with recursive tree as (
select 1 as level, l1.linkcaseccin as cci, l1.linkcategorycode as lcode
from hclive.linkedmatters l1
where l1.maincaseccin ='001003201400100'
and l1.linkcategorycode='I'
union all
select p.level + 1, c1.linkcaseccin as cci, c1.linkcategorycode as lcode
from hclive.linkedmatters c1
join tree p on p.maincaseccin = c1.linkcaseccin
where c1.linkcategorycode='I'
)
select coalesce(rpad('IN',16,' ') || rpad( m.casetype||'/' || m.casenumber || '/' || m.caseyear,16, ' '),' ') as inmatter
from tree t
join hclive.main M on m.ccin = t.cci;
The level column does not seem to be necessary as you don't use it at all in your query, but I left in there as an example to get the same information in Postgres.

Msg 8114: Error converting data type varchar to numeric

I am writing a dynamic query in SSMS 2008 and I get the above error. What is the cause of this?
My query:
SELECT TOP 10 *
FROM
ALL_COMPLAINTS A
JOIN
#TEMP5 B ON A.QXP_EXCEPTION_NO = B.QXP_EXCEPTION_NO
AND A.[LEVEL] = B.[LEVEL]
AND A.[QXP_REPORT_DATE] = B.[QXP_REPORT_DATE]
WHERE
A.QXP_REPORT_DATE >= CONVERT(DATETIME, '' + #FirstMonthDate + ' 00:00:00', 102)
AND
A.QXP_REPORT_DATE <= CONVERT(DATETIME, '' + #LastMonthDate + ' 23:59:59', 102)
AND
A.QXP_SHORT_DESC <> 'Design Control' AND A.LEVEL = ' + CAST(#TheLevel AS VARCHAR(5)) + '
I know that A.Level is numeric and I also know that I do not get any errors if I just remove the A.Level portion. However, I am not certain I am casting #TheLevel correctly since this is dynamic SQL.
Your quotes are messed up in the last line, you cant mix dynamic and non dynamic SQL in the same statement. Also assuming #TheLevel is a numeric, if #TheLevel is a char, you need to convert it to a numeric (int I assume in this case)
SELECT TOP 10 *
FROM
ALL_COMPLAINTS A
JOIN
#TEMP5 B ON A.QXP_EXCEPTION_NO = B.QXP_EXCEPTION_NO
AND A.[LEVEL] = B.[LEVEL]
AND A.[QXP_REPORT_DATE] = B.[QXP_REPORT_DATE]
WHERE
A.QXP_REPORT_DATE >= CONVERT(DATETIME, '' + #FirstMonthDate + ' 00:00:00', 102)
AND
A.QXP_REPORT_DATE <= CONVERT(DATETIME, '' + #LastMonthDate + ' 23:59:59', 102)
AND
A.QXP_SHORT_DESC <> 'Design Control' AND A.LEVEL = #TheLevel
If you need a dynamic portion then it is probably good practice to pre evaluate it and then key it into the non dynamic query

Get index of row within a group?

I have two tables:
Unit:
UnitId int PK
Title varchar
UnitOption:
UnitOptionId int PK
UnitId int FK
Title varchar
Quote:
QuoteId int PK
UnitOptionId int FK
Title varchar
I want to create a scalar UDF that takes a QuoteId param and returns a varchar that contains the following description (pseudu):
Quote.Title + '-' + Unit.Title + '-' + Unit.UnitId +
/* Here is where my question is:
If there are more than 1 UnitOption under this Unit, then
return '-' + the UnitOption number under this Unit
(i.e.) if under this Unit, there are 3 UnitOption with IDs 13, 17, 55
under the unit, and the current Quote.UnitOptionId is the 17 one,
it should return 2.
Which means I want to retrieve an ID of this row in the group.
Else
return ''
*/
If you're using SQL 2005 or later and I've interpreted your question correctly, you should be able to adapt the following into your function.
WITH [UnitExt] AS
(
SELECT
[Unit].[UnitId],
[Unit].[Title],
COUNT(*) AS [Count]
FROM [Unit]
INNER JOIN [UnitOption] ON [UnitOption].[UnitId] = [Unit].[UnitId]
GROUP BY
[Unit].[UnitId],
[Unit].[Title]
)
SELECT
[Quote].[Title] + '-' + [UnitExt].[Title] + '-' + [UnitExt].[UnitId] +
CASE
WHEN [UnitExt].[Count] > 1 THEN '-' +
CAST([UnitOption].[UnitOptionId] AS varchar(max))
ELSE ''
END
FROM [Quote]
INNER JOIN [UnitOption] ON [UnitOption].[UnitOptionId] =
[Quote].[UnitOptionId]
INNER JOIN [UnitExt] ON [UnitExt].[UnitId] = [UnitOption].[UnitId]
WHERE [Quote].[QuoteId] = #QuoteId
Something like this should do it.
SELECT DISTINCT Quote.Title +
' - ' + Unit.Title +
' - ' + Unit.UnitId +
CASE
WHEN COUNT(*) OVER(PARTITION BY Quote.Id) > 0
THEN
' - ' + CAST(ROW_NUMBER() OVER (PARTITION BY Quote.Id ORDER BY Quote.UnitOptionId) AS varchar)
ELSE
''
END
FROM Quote
JOIN UnitOption ON UnitOption.Id = Quote.UnitOptionId
JOIN Unit ON Unit.Id = UnitOption.UnitId
WHERE Quote.Id = #QuoteId
CREATE FUNCTION ufnGetDescription
(#QuoteID INT)
RETURNS VARCHAR(MAX)
AS
BEGIN
DECLARE #RetVal VARCHAR(MAX);
WITH CurRow
AS (SELECT quote.title + '- ' + unit.title AS start,
u.unitid,
quoteid,
uo.unitoptionid
FROM quote
INNER JOIN unitoption uo
ON quote.unitoptionid = uo.unitoptionid
INNER JOIN unit
ON uo.unitid = unit.unitid
WHERE quote.quoteid = #QuoteID),
AllUnits
AS (SELECT u.unitid,
uo.unitoptionid,
Row_number()
OVER(PARTITION BY u.unitid ORDER BY uo.unitoptionid) AS NUMBER,
Count(* )
OVER(PARTITION BY u.unitid ) AS cntUnits
FROM unit
INNER JOIN unionoption uo
ON unit.unitid = uo.unitid
WHERE u.unitid IN (SELECT unitid
FROM CurRow))
SELECT #RetVal = CASE
WHEN a.cntUnits = 1 THEN ''
ELSE r.start + '-' + Cast(NUMBER AS VARCHAR(max))
END
FROM AllUnits a
INNER JOIN CurRow r
ON a.unitoptionid = r.unitoptionid
RETURN #RetVal
END