Sql Server use CONTAINS function as column in a select statement - sql

I am writing a select statement and I would like it to include in the list of columns a call to the CONTAINS function in sql server.
I want it to be something like this:
SELECT i.IncidentID, CONTAINS(sa.AddressStreet, 'asda') AS 'asda' FROM Incident i
JOIN IncidentSubject isu ON isu.IncidentID = i.IncidentID
JOIN SubjectAddress sa ON sa.SubjectID = isu.SubjectID
WHERE i.Section <> 0 AND (i.Section & 255 <> 0)
But I get an error when using contains in the columns sections. With other functions such as LEN is works.

CONTAINS is a predicate used in the WHERE clause of a Transact-SQL SELECT statement to perform SQL Server full-text search on full-text indexed columns containing character-based data types.
It means, could not be used in SELECT.
However, as I understand correctly you can use CharIndex
SELECT i.IncidentID,
CHARINDEX('asda', sa.AddressStreet) 'asda'
FROM Incident i
JOIN IncidentSubject isu ON isu.IncidentID = i.IncidentID
JOIN SubjectAddress sa ON sa.SubjectID = isu.SubjectID
WHERE i.Section <> 0
AND (i.Section&255 <> 0);
See more on CONTAINS (Transact-SQL) and CHARINDEX (Transact-SQL)

As JohnHC already pointed out CONTAINS is a predicate that can be used in WHERE clauses only.
You could try this instead
SELECT
i.IncidentID,
CASE WHEN CHARINDEX('asda', sa.AddressStreet) > 0 THEN 'true' else 'false' end AS 'asda'
FROM Incident i
JOIN IncidentSubject isu ON isu.IncidentID = i.IncidentID
JOIN SubjectAddress sa ON sa.SubjectID = isu.SubjectID
WHERE i.Section <> 0 AND (i.Section & 255 <> 0)

Are you looking for this?
SELECT
i.IncidentID,
sa.AddressStreet [asda]
FROM Incident i
JOIN IncidentSubject isu ON isu.IncidentID = i.IncidentID
JOIN SubjectAddress sa ON sa.SubjectID = isu.SubjectID
WHERE i.Section <> 0
AND (i.Section&255 <> 0)
AND CONTAINS(sa.AddressStreet, 'asda');

Related

How to solve this error: Cannot perform an aggregate function on an expression containing an aggregate or a subquery?

I have a query that works on SQLAnywhere, but for some reason does not work on SSMS, tell me what is wrong with it, because I get an error: Cannot perform an aggregate function on an expression containing an aggregate or a subquery.
SELECT (CASE
WHEN EXISTS (select 1 from READCHK_READSEQ_OVRCOMP where READCHK_ID = :readChkId AND READSEQ_ID = :readSeqId) THEN 'M'
WHEN ( COUNT(*) = Coalesce(SUM((SELECT COUNT(*) FROM READCHKFLEX flx WHERE flx.READCHKFLD_ID = rcfld.READCHKFLD_ID AND flx.READCHK_ID = :readChkId) ), 0 )) THEN 'A'
ELSE 'I' END) CompletionStatus
FROM READSEQFLD rsfld
JOIN READSEQ rseq on rseq.READSEQ_ID = rsfld.READSEQ_ID
JOIN READCHKPAGEFLD rcpf on rcpf.READCHKTYPE_ID = rseq.READCHKTYPE_ID and rcpf.READCHKFLD_ID = rsfld.READCHKFLD_ID
JOIN READCHKFLD rcfld on rcfld.READCHKFLD_ID = rcpf.READCHKFLD_ID
WHERE rsfld.READSEQ_ID = :readSeqId
AND Upper(rsfld.ACTIVATE_FLG) = 'Y'
AND rcfld.CALFORM_ID IS NULL
AND (rcpf.fld_properties is null or Upper(rcpf.fld_properties) <> 'HIDE');
How to fix that?
SQL Server doesn't allow aggregates on expressions containing sub queries.
I think the following should preserve your original behaviour
Append a CTE definition before the existing SELECT
WITH flx_agg
AS (SELECT COUNT(*) AS Cnt,
READCHKFLD_ID
FROM READCHKFLEX flx
WHERE flx.READCHK_ID = :readChkId
GROUP BY READCHKFLD_ID)
SELECT ...
Add an outer join to that to your existing join conditions
LEFT JOIN flx_agg
ON flx_agg.READCHKFLD_ID = rcfld.READCHKFLD_ID
Change the offending CASE WHEN condition to
WHEN COUNT(*) = COALESCE(SUM(flx_agg.Cnt), 0)

IF THEN in SQL Select Statement

I'm writing a report to return vendor names from journal transactions. Here are the basics of the query below.
I am using data from two views:
Journal detail view = pa_journal_detail
Vendor detail view = ap_vendor
Match on Vendor Number:
The vendor number is contained in the following fields:
ap_vendor.a_vendor_number
pa_journal_detail.jl_ref1 [under certain criteria shown below] ONLY WHEN the journal source code is "API" or "APM"
The source code is stored in the field pa_journal_detail. jl_source_code
The vendor name is stored in the field ap_vendor.a_vendor_name
This is the query I had started with. It is returning incorrect syntax errors when I attempt to run.
SELECT
CASE
WHEN pa_journal_detail. jl_source_code = ‘API’
OR pa_journal_detail. jl_source_code = ‘APM’
THEN(
SELECT a_vendor_name
FROM ap_vendor
INNER JOIN pa_journal_detail
ON pa_journal_detail.jl_ref1 = ap_vendor.a_vendor_number)
ELSE 0
END as a_vendor_name, *
FROM pa_journal_detail
Here is the full query below. I have also tried it with the "TOP 1" included as well. I am now getting the error that there is incorrect syntax near the keyword AS.
SELECT
pa_journal_detail.a_project
,pa_journal_detail.jl_seg2
,pa_journal_detail.jl_seg3
,pa_journal_detail.jl_seg4
,pa_journal_detail.jl_source_code
,pa_journal_detail.jl_ref1
,pa_journal_detail.jl_gl_org
,pa_journal_detail.jl_gl_obj
,pa_journal_detail.jl_line_num
,pa_journal_detail.jl_journal_num
,pa_journal_detail.jl_jnl_year_period
,pa_journal_detail.jl_journal_number
,pa_journal_detail.jl_journal_seq
,(SELECT(CASE
WHEN pa_journal_detail. jl_source_code = 'API'
OR pa_journal_detail. jl_source_code = 'APM'
THEN(
SELECT TOP 1 a_vendor_name
FROM ap_vendor
RIGHT JOIN pa_journal_detail
ON pa_journal_detail.jl_ref1 = ap_vendor.a_vendor_number
)
ELSE 0
END as 'a_vendor_name', *
FROM pa_journal_detail))
FROM pa_journal_detail
This is what I ended up with and its working now! Thank you all!
SELECT
pa_journal_detail.a_project
,pa_journal_detail.jl_seg2
,pa_journal_detail.jl_seg3
,pa_journal_detail.jl_seg4
,pa_journal_detail.jl_source_code
,pa_journal_detail.jl_ref1
,pa_journal_detail.jl_gl_org
,pa_journal_detail.jl_gl_obj
,pa_journal_detail.jl_line_num
,pa_journal_detail.jl_journal_num
,pa_journal_detail.jl_jnl_year_period
,pa_journal_detail.jl_journal_number
,pa_journal_detail.jl_journal_seq
,iif((pa_journal_detail.jl_source_code = 'API'
OR pa_journal_detail.jl_source_code = 'APM')
,(SELECT TOP 1 a_vendor_name
FROM ap_vendor
RIGHT JOIN pa_journal_detail
ON pa_journal_detail.jl_ref1 = ap_vendor.a_vendor_number)
,0) as 'a_vendor_name'
FROM pa_journal_detail
for string compare you need to use single quote
CASE
WHEN pa_journal_detail. jl_source_code = 'API'
OR pa_journal_detail. jl_source_code = 'APM'
THEN(
SELECT top 1 a_vendor_name -- here you need limit or top 1
FROM ap_vendor
INNER JOIN pa_journal_detail
ON pa_journal_detail.jl_ref1 = ap_vendor.a_vendor_number
)
ELSE 0
END as a_vendor_name, *
FROM pa_journal_detail
There is also iif(). I use it far more often than I should, I just like have a tiny little if for simple conditional work instead of big ole' Case statement.
select iif(1 = 1,'True','False')
-- any series that results in a boolean
select iif((1 = 1 and 0 = 0) and (5 / 1 = 5 and 5 % 10 = 5),'True','False')
for your query
SELECT
pa_journal_detail.a_project
,pa_journal_detail.jl_seg2
,pa_journal_detail.jl_seg3
,pa_journal_detail.jl_seg4
,pa_journal_detail.jl_source_code
,pa_journal_detail.jl_ref1
,pa_journal_detail.jl_gl_org
,pa_journal_detail.jl_gl_obj
,pa_journal_detail.jl_line_num
,pa_journal_detail.jl_journal_num
,pa_journal_detail.jl_jnl_year_period
,pa_journal_detail.jl_journal_number
,pa_journal_detail.jl_journal_seq
,iif(pa_journal_detail.jl_source_code = 'API' OR pa_journal_detail.jl_source_code = 'APM',(SELECT TOP 1 a_vendor_name
FROM ap_vendor
RIGHT JOIN pa_journal_detail
ON pa_journal_detail.jl_ref1 = ap_vendor.a_vendor_number)
,0)
'a_vendor_name', *
FROM pa_journal_detail))
FROM pa_journal_detail
I think a case expression may be the wrong tool for the job. If you want to join a table sometimes, a left join may be easier:
SELECT p.*, a.a_vendor_name
FROM pa_journal_detail p
LEFT JOIN ap_vendor a ON p.jl_ref1 = a.a_vendor_number AND
p.jl_source_code IN ('API', 'APM')

How to use a non-existing column in sql query

I am working in SQL server 2012. I have to write a sql statement where I first assign a value to [Pay_Type], which is a non-existing column (not sure whether it can be called as variable or not) and based upon its value I want to use it in another case statement as shown below
SELECT sp.First_Name, [Pay_Type] = CASE WHEN NOT EXISTS(SELECT '1' FROM
PERSON_SALARY ps WHERE ps.PARTY_ID = sp.PARTY_ID and ps.END_DATE IS NULL)
THEN 'Hourly' ELSE 'Salary' END,
HOURLY_RATE = CASE WHEN [Pay_Type] = 'Hourly' THEN pj.HOURLY_RATE ELSE
'0.00' END
FROM SEC_PERSON sp
LEFT OUTER JOIN PERSON_JOB pj ON sp.PERSON_ID = pj.PERSON_ID
WHERE sp.END_DATE IS NOT NULL
But I am getting "Invalid column name 'Pay_Type' " error.
Column aliases cannot be re-used in the same SELECT where they are define. The typical answer is to use a subquery or CTE. I also like using a lateral join:
SELECT sp.First_Name, s.Pay_Type,
HOURLY_RATE = (CASE WHEN s.Pay_Type = 'Hourly' THEN pj.HOURLY_RATE ELSE
'0.00' END)
FROM SEC_PERSON sp LEFT OUTER JOIN
PERSON_JOB pj
ON sp.PERSON_ID = pj.PERSON_ID OUTER APPLY
(SELECT (CASE WHEN NOT EXISTS (SELECT 1
FROM PERSON_SALARY ps
WHERE ps.PARTY_ID = sp.PARTY_ID and ps.END_DATE IS NULL
)
THEN 'Hourly' ELSE 'Salary'
END) as PayType
) s
WHERE sp.END_DATE IS NOT NULL

How can I refactor this query

How can I rewrite this SQL code? I would like to avoid the repetitive execution of the case for every record.
SELECT chcr.chsid,
CASE
WHEN EXISTS
(SELECT 1
FROM hdr_run chre,
clmerr ce
WHERE chre.chsid = chcr.chsid
AND chre.run_nmbr < chcr.last_run_nmbr
AND chre.clm_error_sid = ce.clm_error_sid
GROUP BY chre.chsid
HAVING COUNT(chre.clm_error_sid) > 0
)
THEN 'Appended'
ELSE 'Never Appended'
END Run_Detail
FROM
clm_res chcr,
clm_der chde
WHERE chde.chsid = chcr.chsid
Have a look at that query please:
SELECT
chcr.chsid,
CASE
WHEN ce.clm_error_sid IS NOT NULL AND COUNT(chre.clm_error_sid, 0) > 0
THEN 'Appended'
ELSE 'Never Appended'
END Run_Detail
FROM
clm_res chcr
JOIN clm_der chde ON chde.chsid = chcr.chsid
LEFT JOIN hdr_run chre ON chre.chsid = chcr.chsid AND chre.run_nmbr < chcr.last_run_nmbr
LEFT JOIN clmerr ce ON chre.clm_error_sid = ce.clm_error_sid
GROUP BY chcr.chsid
If there's more than one clm_der for each clm_res based on their chsid, we'd have to double check that the COUNT is not counting the extras from clm_der.
I have no data to test this on so all I can go on is the SQL you've provided but from a brief look it does not appear that the GROUP BY and HAVING COUNT() > 0 statements are required as the combination of the INNER JOIN condition in the sub-query and the use of EXISTS in the outer query does the same thing.
Does this have exactly the same functionality:
SELECT chcr.chsid,
CASE
WHEN EXISTS
( SELECT 1
FROM hdr_run chre
INNER JOIN
clmerr ce
ON (chre.clm_error_sid = ce.clm_error_sid)
WHERE chre.chsid = chcr.chsid
AND chre.run_nmbr < chcr.last_run_nmbr
)
THEN 'Appended'
ELSE 'Never Appended'
END Run_Detail
FROM clm_res chcr
INNER JOIN
clm_der chde
ON ( chde.chsid = chcr.chsid );
SQLFIDDLE
Also, repeated execution of the CASE statement is not a bad thing as the optimizer should not duplicate executions of the sub-query.

SQL Server query with CASE and GROUP BY, field invalid?

Can't figure out what I'm doing wrong here. It says field HasNoteDate is invalid. I just want it to return 1 if there's a date, 0 if there's not and I wanted it grouped so I can get the counts and the sum of loan amounts. I've looked at the stackoverflow answers for grouping by a case and none of them are solving it for me. Thanks!
SELECT dbo.BDONAMES.UserID, dbo.BRKRMAST.Tier, dbo.BDONAMES.REGION, COUNT(*) AS TierRegionCount,
SUM(dbo.LOAN.LOAN_AMT) AS LoanAmtSum, dbo.LOAN.DEAL_STATUS, CASE WHEN dbo.WORKFLOW.NOTE_DATE IS NULL
THEN 0 ELSE 1 END AS HasNoteDate
FROM dbo.BRKRMAST INNER JOIN
dbo.BRKRREF ON dbo.BRKRMAST.BRKRMASTID = dbo.BRKRREF.BRKRMASTID INNER JOIN
dbo.LOAN ON dbo.BRKRREF.LoanId = dbo.LOAN.LoanId INNER JOIN
dbo.WORKFLOW ON dbo.LOAN.LoanId = dbo.WORKFLOW.LoanId LEFT OUTER JOIN
dbo.BDONAMES ON dbo.BRKRMAST.BDONAMESID = dbo.BDONAMES.BDONAMESID
WHERE (LEN(dbo.BDONAMES.UserID) > 0) AND (dbo.BRKRMAST.Tier > 0) AND (LEN(dbo.BDONAMES.REGION) > 0)
GROUP BY dbo.BDONAMES.UserID, dbo.BRKRMAST.Tier, dbo.BDONAMES.REGION, dbo.LOAN.LOAN_AMT, dbo.LOAN.DEAL_STATUS, HasNoteDate
ORDER BY dbo.BDONAMES.UserID, dbo.BRKRMAST.Tier, dbo.BDONAMES.REGION
logic of SQL query execution is not straightforward as common programming languages
here are sample execution stages for your query:
perform join on tables in FROM CLAUSE
perform GROUP BY - this will cause error, as HasNoteDate is not defined for this moment
perform ORDER BY
perform SELECT - only during this stage column HasNoteDate is defined
so, you cannot use undefined column HasNoteDate in GROUP BY, you have to replace it with your statement (CASE WHEN dbo.WORKFLOW.NOTE_DATE IS NULL THEN 0 ELSE 1 END), then sql server will be able to GROUP
SELECT dbo.BDONAMES.UserID, dbo.BRKRMAST.Tier, dbo.BDONAMES.REGION, COUNT(*) AS TierRegionCount,
SUM(dbo.LOAN.LOAN_AMT) AS LoanAmtSum, dbo.LOAN.DEAL_STATUS, CASE WHEN dbo.WORKFLOW.NOTE_DATE IS NULL
THEN 0 ELSE 1 END AS HasNoteDate
FROM dbo.BRKRMAST INNER JOIN
dbo.BRKRREF ON dbo.BRKRMAST.BRKRMASTID = dbo.BRKRREF.BRKRMASTID INNER JOIN
dbo.LOAN ON dbo.BRKRREF.LoanId = dbo.LOAN.LoanId INNER JOIN
dbo.WORKFLOW ON dbo.LOAN.LoanId = dbo.WORKFLOW.LoanId LEFT OUTER JOIN
dbo.BDONAMES ON dbo.BRKRMAST.BDONAMESID = dbo.BDONAMES.BDONAMESID
WHERE (LEN(dbo.BDONAMES.UserID) > 0) AND (dbo.BRKRMAST.Tier > 0) AND (LEN(dbo.BDONAMES.REGION) > 0)
GROUP BY dbo.BDONAMES.UserID, dbo.BRKRMAST.Tier, dbo.BDONAMES.REGION, dbo.LOAN.DEAL_STATUS, CASE WHEN dbo.WORKFLOW.NOTE_DATE IS NULL
THEN 0 ELSE 1 END
ORDER BY dbo.BDONAMES.UserID, dbo.BRKRMAST.Tier, dbo.BDONAMES.REGION
Use columns in your group by exactly the way you have defined in you select Statement, otherwise SQL server tries to GROUP it with the fields that it cannot find in SELECT statement and throws an error.