Assign a value to a variable in a select statement and then used to find value in nested select statement - sql

I'm getting the error
A SELECT statement that assigns a value to a variable must not be combined with data-retrieval operations.
Here's my SELECT statement.
SELECT A.vendor_id, **#vendor_employee** = A.vendor_employee_id
, B.txt_first_name, B.txt_last_name,
SELECT txt_Vendor_Employee_Detail_Element,
(CASE
WHEN txt_Vendor_Employee_Detail_Value <> ''
AND txt_Vendor_Employee_Detail_Value IS NOT NULL
THEN txt_Vendor_Employee_Detail_Value
ELSE CONVERT(VARCHAR, txt_Vendor_Employee_Detail_Date)
END) AS Vendor_Detail_Element_Value
FROM t_vendor_employee_detail
WHERE vendor_employee_id = **#vendor_employee**)
FROM...

Yes, basically you can't return data and assign variables in the same select statement. What I think you intend to do is a correlated subquery which references an outer value.
That wolud look something like this:
SELECT A.vendor_id, A.vendor_employee_id
, B.txt_first_name, B.txt_last_name,
(SELECT d.txt_Vendor_Employee_Detail_Element
FROM t_vendor_employee_detail d
WHERE d.vendor_employee_id = A.Vendor_employee_id /* references outside the subqquery */)
FROM...
but you are also returning multiple rows in your subquery which should probably be rewritten as a join.
SELECT A.vendor_id, A.vendor_employee_id
, B.txt_first_name, B.txt_last_name,
d.txt_Vendor_Employee_Detail_Element,
(CASE
WHEN D.txt_Vendor_Employee_Detail_Value <> ''
AND d.txt_Vendor_Employee_Detail_Value IS NOT NULL
THEN d.txt_Vendor_Employee_Detail_Value
ELSE CONVERT(VARCHAR, d.txt_Vendor_Employee_Detail_Date)
END) AS Vendor_Detail_Element_Value
FROM vendor_table_A A
INNER JOIN t_vendor_employee_detail d
ON d.vendor_employee_id = A.vendor_employee_id
INNER JOIN vendor_table_B B
ON...
These examples will give you the basic idea but we would really need the whole query to give you a complete solution.

This looks like something that could be rewritten using a JOIN. It's hard to say how without seeing the whole query, but here is an attempt:
SELECT A.vendor_id, A.vendor_employee_id
, B.txt_first_name, B.txt_last_name,
c.txt_Vendor_Employee_Detail_Element,
(CASE
WHEN c.txt_Vendor_Employee_Detail_Value <> ''
AND c.txt_Vendor_Employee_Detail_Value IS NOT NULL
THEN c.txt_Vendor_Employee_Detail_Value
ELSE CONVERT(VARCHAR, c.txt_Vendor_Employee_Detail_Date)
END) AS Vendor_Detail_Element_Value
FROM ...
INNER JOIN t_vendor_employee_detail c
ON c.vendor_employee_id = A.vendor_employee_id
As the error message says, you cannot use a variable in the way you are trying.

You can retrieve and assign data altogether using a merge statement.
Something like this:
DECLARE #ID TABLE (
ID INT
)
MERGE INTO #ID
USING (
select 1 a,2 b,3 c
) as src
ON ( 1 = 2 )
WHEN NOT MATCHED THEN
INSERT (ID)
VALUES (Src.a)
OUTPUT src.b, src.c
;
SELECT * FROM #ID

Related

How to insert data into table with case expression? [duplicate]

I have a query like this:
SELECT
jobs.*,
(
CASE
WHEN lead_informations.state IS NOT NULL THEN lead_informations.state
ELSE 'NEW'
END
) AS lead_state
FROM
jobs
LEFT JOIN lead_informations ON
lead_informations.job_id = jobs.id
AND
lead_informations.mechanic_id = 3
WHERE
lead_state = 'NEW'
Which gives the following error:
PGError: ERROR: column "lead_state" does not exist
LINE 1: ...s.id AND lead_informations.mechanic_id = 3 WHERE (lead_state...
In MySql this is valid, but apparently not in Postgresql. From what I can gather, the reason is that the SELECT part of the query is evaluated later than the WHERE part. Is there a common workaround for this problem?
I struggled on the same issue and "mysql syntax is non-standard" is not a valid argument in my opinion. PostgreSQL adds handy non-standard extensions as well, for example "INSERT ... RETURNING ..." to get auto ids after inserts. Also, repeating large queries is not an elegant solution.
However, I found the WITH statement very helpful (CTE's). It sort of creates a temporary view within the query which you can use like a usual table then. I'm not sure if I have rewritten your JOIN correctly, but in general it should work like this:
WITH jobs_refined AS (
SELECT
jobs.*,
(SELECT CASE WHEN lead_informations.state IS NOT NULL THEN lead_informations.state ELSE 'NEW' END) AS lead_state
FROM jobs
LEFT JOIN lead_informations
ON lead_informations.job_id = jobs.id
AND lead_informations.mechanic_id = 3
)
SELECT *
FROM jobs_refined
WHERE lead_state = 'NEW'
You would need to either duplicate the case statement in the where clause, or my preference is to do something like the following:
SELECT *
FROM (
SELECT
jobs.*,
(CASE WHEN lead_informations.state IS NOT NULL THEN lead_informations.state ELSE 'NEW' END) as lead_state
FROM
"jobs"
LEFT JOIN lead_informations ON lead_informations.job_id = jobs.id
AND lead_informations.mechanic_id = 3
) q1
WHERE (lead_state = 'NEW')
MySQL's support is, as you experienced, non-standard. The correct way is to reprint the same expression used in the SELECT clause:
SELECT
jobs.*,
CASE
WHEN lead_informations.state IS NOT NULL THEN lead_informations.state
ELSE 'NEW'
END AS lead_state
FROM
jobs
LEFT JOIN lead_informations ON
lead_informations.job_id = jobs.id
AND
lead_informations.mechanic_id = 3
WHERE
lead_informations.state IS NULL
I believe the common solution is to use an inner SELECT for the calculation (or CASE statement in this case) so that the result of the inner SELECT is available to the entire outer query by the time the execution gets to that query. Otherwise, the WHERE clause is evaluated first and knows nothing about the SELECT clause.
Subquery:
SELECT "tab_1"."BirthDate", "tab_1"."col_1" FROM (
SELECT BirthDate, DATEADD(year, 18, BirthDate) AS "col_1" FROM Employees
) AS "tab_1"
WHERE "tab_1"."col_1" >= '2000-12-31';
I used alias in where like this. (Sub Query).
Select "Vendors"."VendorId", "Vendors"."Name","Result"."Total"
From (Select "Trans"."VendorId", ("Trans"."A"+"Trans"."B"+"Trans"."C") AS "Total"
FROM "Trans"
WHERE "Trans"."Year"=2014
) As "Result"
JOIN "Vendors" ON "Result"."VendorId"="Vendors"."VendorId"
WHERE "Vendors"."Class"='I' AND "Result"."Total" > 200

SQL query having CASE WHEN EXISTS statement

I trying to create a SQL query with a CASE WHEN EXISTS clause in SQL Server. I assume I am doing something wrong as when I run the SELECT * FROM [Christmas_Sale] it takes forever for SQL to load the code.
CREATE VIEW [Christmas_Sale]
AS
SELECT
C.*,
CASE
WHEN EXISTS (SELECT S.Sale_Date
FROM [Christmas_Sale] s
WHERE C.ID = S.ID)
THEN 0
ELSE 1
END AS ChristmasSale
FROM
[Customer_Detail] C ;
I'm trying to write a sub select which I need to return a 1 if Sale_Date= 1 and 0 for anything else.
The syntax of your query looks ok. But since your stated:
I'm trying to write a sub select which I need to return a 1 if Sale_Date= 1 and 0 for anything else.
... Then you could rephrase your query by adding one more condition in the WHERE clause of the subquery:
CREATE VIEW [Christmas_Sale]AS
SELECT
C.*,
CASE WHEN EXISTS (
SELECT 1
FROM [Christmas_Sale] s
WHERE C.ID = S.ID and S.Sale_Date = 1
) THEN 0 ELSE 1 END AS ChristmasSale
FROM [Customer_Detail] C ;
If a record exists in [Christmas_Sale] with the corresponding ID and Sale_Date = 1, then ChristmasSale will have value 1, else it will display 0.
This query looks correct:
CREATE VIEW [Christmas_Sale] AS
SELECT C.*,
(CASE WHEN EXISTS (SELECT 1
FROM [Christmas_Sale] s
WHERE C.ID = S.ID
)
THEN 0 ELSE 1
END) AS ChristmasSale
FROM [Customer_Detail] C ;
If performance is an issue, you want an index on Christmas_Sale(ID).
Note that the SELECT S.Sale_Date in the subquery is meaningless, because EXISTS checks for rows not columns. Hence, I replaced it with the simpler 1.

If else condition in MSSQL

Suppose I have serial number, test name and few other columns, i want to write a condition if TESTNAME is null for a particular serial number then set the TESTNAME to blank else perform inner join
SELECT
(A.PTNUMBER + '-' +A.SL_NO) AS ENUMBER,
D.ENGINEER AS REQ, D.DATETIME as "DATE",
(select Value
from DROPDOWN
where B.TEST_NAME=CONVERT(VARCHAR,DropdownID)) TESTNAME,
TABLE_NAME AS TABLETD
FROM INSPECTION D
INNER JOIN TABLEA A ON D.ENGID = CONVERT(VARCHAR,A.EN_ID)
INNER JOIN TABLEB B ON B.ENGID = CONVERT(VARCHAR,A.EN_ID)
INNER JOIN TABLEC C ON C.ENGID = CONVERT(VARCHAR,A.EN_ID)
not sure what you mean by set testname to blank but if you meant to be using a SELECT query then you can do like
select *,
case when TESTNAME is null and serial_number = some_value then '' end as TESTNAME
from mytable
You could combine a case expression and coalesce() along with your join to choose the value you want to return.
select serial_number, ...
,case when coalesce(testname,'') <> ''
then t2.testname
else coalesce(testname,'') end
from t
inner join t2
on ...
You can use isnull() or coalesce() in sql server to return a different value to replace null.
select isnull(testname,'')
or
select coalesce(testname,'')
The main difference between the two is that coalesce() can support more than 2 parameters, and it selects the first one that is not null. More differences between the two are answered here.
select coalesce(testname,testname2,'')
coalesce() is also standard ANSI sql, so you will find it in most RDBMS. isnull() is specific to sql server.
Reference:
isnull() - msdn
coalesce() - msdn
SELECT (A.PTNUMBER + '-' + A.SL_NO) AS ENUMBER,
D.ENGINEER AS REQ,
D.DATETIME as "DATE",
case
when SerialNo = xxx and TESTNAME is null then ''
else (select Value from DROPDOWN where B.TEST_NAME = CONVERT(VARCHAR, DropdownID))
end AS TESTNAME,
TABLE_NAME AS TABLETD
FROM INSPECTION D
INNER JOIN TABLEA A ON D.ENGID = CONVERT(VARCHAR, A.EN_ID)
INNER JOIN TABLEB B ON B.ENGID = CONVERT(VARCHAR, A.EN_ID)
INNER JOIN TABLEC C ON C.ENGID = CONVERT(VARCHAR, A.EN_ID);

teradata SQL tuning pundits - SELECT Failed. 3771: Illegal expression in WHEN clause of CASE expression

I am using a statement as below and get this error:
SELECT Failed. 3771: Illegal expression in WHEN clause of CASE
expression.
I had better hopes from Teradata. SQL Server can do it but Teradata can't.
How can I work around this? Any solution?
sel ( CASE
WHEN EXISTS ( sel '1' from VolatileTable Dtb1 where Dtb1.c1=FACT_Table_5MillionRows.C1)
THEN "FACTTablew5MillionRows"."CustomColumName"
ELSE 'ALL OTHER'
END ) (NAMED "CustomColumName" )
from
"Db"."FACTTablew5MillionRows"
Replace
WHEN EXISTS (...)
By
WHEN 1 = (SELECT 1 WHERE EXISTS (...))
Teradata doesn't like EXISTS in Correlated Scalar Subqueries within a CASE, but you can rewrite it like this:
select
( CASE
WHEN C1 = ( select MIN(C1) from VolatileTable Dtb1
where Dtb1.c1=ft.C1)
THEN ft."CustomColumName"
ELSE 'ALL OTHER'
END ) (NAMED "CustomColumName" )
from
"Db"."FACTTablew5MillionRows" as ft
If VolatileTable.C1 is unique you can remove the MIN.
But in 95% logic like this can be replaced by a LEFT JOIN:
select
ft.*,
CASE WHEN Dtb1.c1 IS NOT NULL
THEN ft."CustomColumName"
ELSE 'ALL OTHER'
end as "CustomColumName"
from "Db"."FACTTablew5MillionRows" as ft
left join VolatileTable Dtb1
on Dtb1.c1=ft.C1
This will return duplicated rows if VolatileTable.C1 is not unique, then you need to change it to:
from "Db"."FACTTablew5MillionRows" as ft
left join (select distinct C1 from VolatileTable) Dtb1
on Dtb1.c1=ft.C1
WHEN EXISTS (select '1' from VolatileTable Dtb1
where Dtb1.c1=FACT_Table_5MillionRows.C1)
THEN somevalue --or a statement that yields a scalar value
You were selecting a column in the then part, where you should be assigning a unique value.

Creating a view in SQL with a case statement in the select

I know something must be wrong with my syntax but I can't seem to figure it out.
I want to populate this column prop_and_cas_dtl_prdct_desc from either expir_prop_and_cas_dtl_prdct_cd or ren_prop_and_cas_dtl_prdct_cd depending on the value in type_indicator but before it goes into prop_and_cas_dtl_prdct_desc it should look up the prop_and_cas_dtl_prdct_desc from pc_ref_detail_product_cd and select the one corresponding to its expir_prop_and_cas_dtl_prdct_cd or ren_prop_and_cas_dtl_prdct_cd.
I apologize for the terrible indenting, I know it is difficult to read but this is the best way I know how to put it.
select
,ren_prop_and_cas_dtl_prdct_cd
...
,p_and_c_cd
,case when type_indicator in ('R','C') then
select prop_and_cas_dtl_prdct_desc
from pc_ref_detail_product_cd a inner join op_pif_coverage_rpc_new b
on a.prop_and_cas_dtl_prdct_cd = b.expir_prop_and_cas_dtl_prdct_cd
else when type_indicator in ('N','O') then
select prop_and_cas_dtl_prdct_desc
from pc_ref_detail_product_cd a inner join op_pif_coverage_rpc_new b
on a.prop_and_cas_dtl_prdct_cd = b.ren_prop_and_cas_dtl_prdct_cd
else NULL
END
AS prop_and_cas_dtl_prdct_desc
FROM dbo.op_pif_coverage_rpc_new
Here is the code I used to create my reference table
create table pc_ref_detail_product_cd(
prop_and_cas_dtl_prdct_cd char(2),
prop_and_cas_dtl_prdct_desc char(30)
)
insert into pc_ref_detail_product_cd (prop_and_cas_dtl_prdct_cd, prop_and_cas_dtl_prdct_desc)
values ('01', 'CORE'),
('02', 'FORECLOSED'),
('04', 'TRUST'),
('06', 'MORTGAGE HOLDERS E&O'),
('07', 'SECURITY INTEREST E&O')
If you need to select column from different table depending on value in additional column you need to include all tables in query, with appropriate JOIN and than use case statement like so
SELECT CASE WHEN a.MyColumn = 0 THEN b.SomeColumn
WHEN a.MyColumn = 1 THEN a.SomeColumn
END AS SomeColumn
FROM MyTableA AS a
JOIN MyTableB AS b
ON a.ID = b.ID
Instead of select statement in case statement, you just going to select column from ether table that you need for each particular case.
I got it figured out. Here is the SQL I used. Sorry if it wasn't apparent what I wanted to do from my horrible code in the original question.
select
,ren_prop_and_cas_dtl_prdct_cd
...
,p_and_c_cd
,case when type_indicator in ('R','C') then
(select prop_and_cas_dtl_prdct_desc
from pc_ref_detail_product_cd a where expir_prop_and_cas_dtl_prdct_cd = prop_and_cas_dtl_prdct_cd)
when type_indicator in ('N','O') then
(select prop_and_cas_dtl_prdct_desc
prop_and_cas_dtl_prdct_desc
from pc_ref_detail_product_cd a where ren_prop_and_cas_dtl_prdct_cd = prop_and_cas_dtl_prdct_cd)
else NULL
END
AS prop_and_cas_dtl_prdct_desc
FROM dbo.op_pif_coverage_rpc_new