SQL Server : how to declare variable in condition case when - sql-server

I have a problem when running queries with a 'case when'. so I want to create a variable to hold the value of the results of the query 'select' to other tables. like the example below. please help me to get the results I want. thank you.
SELECT
a.field1, a.field2,
a.field3 =
CASE
WHEN a.field1 = 'alfa'
THEN
WHEN
-- I want to declare variable to check get value from another table with query select and condition 'WHERE' with variable declare
var varTest = (SELECT TOP 1 b.field1 FROM Table2 as b WHERE b.field2=a.field2) Then
if varTest = 'actif' then
SELECT (c.field4 * C.field5) as hasil FROM Table2 as c WHERE c.field1=varTest)
ELSE
a.field3
END
FROM
Table1 a(NOLOCK)
WHERE
a.field1 = 'alfa'
This is sample data :
field1 | field2 | field3 | > Table1
alfa idAlfa 0
beta idBeta 0
carlie idCarlie 0
field1 | field2 | field4 | field5 | > Table2
actif idAlfa 80 5
pasif idBeta 50 5
other idCarlie 10 5
Result :
field1 | field2 | field3
alfa idAlfa 400
beta idBeta 250
carlie idCarlie 50

It looks to me like this is what you intended. Hard to be entirely sure. It's also possible that this isn't the most efficient query as it's generally a good idea to avoid subqueries inside case expressions.
a.field3 =
CASE WHEN a.field1 = 'alfa' THEN
CASE WHEN (
SELECT TOP 1 b.field1 FROM Table2 as b
WHERE b.field2 = a.field
) = 'actif'
THEN (
SELECT c.field4 * C.field5 as hasil FROM Table2 as c
WHERE c.field1 = 'actif'
)
ELSE a.field3
END
ELSE null
END

You don't need a variable of any type to accomplish this.
A simple JOIN and CASE will get the active (actif) record, calculate your field4 * field5 result (hasil) or use 0 for all passive (pasif) or other records like so:
SELECT
a.field1,
a.field2,
CASE b.field1 -- check id...
WHEN 'actif'
THEN b.field4 * b.field5 -- if 'actif' record, calculate result
ELSE
a.field3 -- not the 'actif' record, use default value
END AS hasil
FROM Table1 AS a -- join the two tables by id name
LEFT JOIN Table2 AS b
ON a.field2 = b.field2;
If you're using SQL Server 2012, you can condense this CASE statement by using IIF:
SELECT
a.field1,
a.field2,
IIF(b.field1 = 'actif', b.field3 * b.field4, a.field3) AS hasil
FROM Table1 AS a
LEFT JOIN Table2 AS b
ON a.field2 = b.field2;
The results using your sample data from these queries are:
field1 | field2 | hasil
alfa idAlfa 400
beta idBeta 0
charlie idCharlie 0
For future reference, the IF syntax you showed in your sample SQL is invalid. That is used in flow control statements that affect how SQL is executed; usually seen in stored procedures. IF can't be used in expressions. Instead, use CASE or IIF statements.

Related

Select x value within a text - string_to_array

I have a column in table1 that contains names separated with commas, like a,b,c
names
result
a,d,e
a,c,e,f
c,d,f,g
Another column with a single name in table2, like a or b or c
line
name
origin
1
a
US
2
b
UK
3
c
UK
4
d
AUS
5
e
CAN
6
f
UK
7
g
UK
And I want to update table1.result if any names from table1.names are in table2.name & origin = UK.
Tried this, but getting error;
update table1 as t1
set result =
(select name from table2 where origin='UK') = any(string_to_array(t1.names, ','))
Use exists(...) if the result you want is boolean:
update table1 as t1
set result = exists(
select name
from table2
where origin = 'UK'
and name = any(string_to_array(t1.names, ','))
);
Test it in db<>fiddle.
If you want to get the names, use string_agg():
update table1 as t1
set result = (
select string_agg(name, ',')
from table2
where origin = 'UK'
and name = any(string_to_array(t1.names, ','))
);
Db<>fiddle.

How can I join a column on a table using a variable as the column name without using dynamic sql

I am trying to figure out how I can join on a table column where the join column will sometimes defer. There is dozens of columns in the table. I am trying to do this without dynamic sql.
Here is an example table to demonstrate what I mean:
Table
-------------------------------------------------
ID | ObjectID_6 | ObjectId_9 | ObjectId_10 |
-------------------------------------------------
1 | 1 | 23 | 55 |
-------------------------------------------------
For example lets say I obtain the column name to join on and set it as a paramater
#columnName VARCHAR(200)= CONCAT('ObjectID_',countNr) --Value is now ObjectId_9
SQL Query I have tried:
SELECT tmpName.*
FROM tblName
JOIN tblObjectTable
ON tblOjbectTable.#columnName = tmpName.ObjectID
This is not a great problem to solve and outside of dynamic sql your options are slim. The example below is a SQL Server solution, however, with minor tweaking the same construct can be performed in mysql.
One try would be to left join for each possible combination and flag which join is true. In this case, you also have to have branch logic to pick the correct value among from the proper join. If you do this you certainly want to test it against your largest dataset and read a little about parameter sniffing in SQL Server. I would attempt to avoid these types of things if at all possible as they result in non-performant queries. It would not be a bad idea to compare this to the dynamic sql alternative on larger datasets.
DECLARE #ColumnNumber INT = 5
SELECT
tmpName.*,
ColumnValue =
CASE
WHEN #ColumnNumber = 1 THEN T1.Column1
WHEN #ColumnNumber = 2 THEN T2.Column2
WHEN #ColumnNumber = 3 THEN T3.Column3
WHEN #ColumnNumber = 4 THEN T4.Column4
WHEN #ColumnNumber = 5 THEN T5.Column5
ELSE
NULL
END
FROM
tblName
LEFT JOIN tblObjectTable T1 ON T1.Column1 = tmpName.ObjectID AND #ColumnNUmber = 1
LEFT JOIN tblObjectTable T2 ON T2.Column2 = tmpName.ObjectID AND #ColumnNUmber = 2
LEFT JOIN tblObjectTable T3 ON T3.Column3 = tmpName.ObjectID AND #ColumnNUmber = 3
LEFT JOIN tblObjectTable T4 ON T4.Column4 = tmpName.ObjectID AND #ColumnNUmber = 4
LEFT JOIN tblObjectTable T5 ON T5.Column5 = tmpName.ObjectID AND #ColumnNUmber = 5

Consult data on table , fields are related to each other

Hello guys Im just starting with SQl server,
Sorce data
type num1 num2 date1
A 1 2 01/01/2019
b 1 01/02/2019
b 3 05/02/2017
a 1 1 03/02/2019
a 2 3 15/03/2018
b 2 20/12/2018
Expected result
type num1 num2 date1 'date2'
a 1 2 01/01/2019 20/12/2018
a 1 1 03/02/2019 01/02/2019
a 2 3 15/03/2018 05/02/2017
this is the best i made until now, and my date2 are all messed up im not getting the correct values , and i still have the problem with dates that the same number can exist in diferent years num1 1 type b exist in 2017 and 2019
select c1.type, c1.num1, c1.num2, c1.date, c2.date as 'date2'
from t1 c1
inner join t1 c2 on c2.num2=c1.num1
order by c1.type
Thanks for your help
I think this is as simple as:
SELECT
t1.[type],
t1.num1,
t1.num2,
t1.date1,
t2.date1 AS date2
FROM
t1
LEFT JOIN t2 ON t2.num1 = t1.num2 AND t2.num2 IS NULL
ORDER BY
t1.[type];
But note that I had to make the requirement up to some degree, as it wasn't entirely clear from your question.
What you need to do is join on yourself, then allow date
Declare #table1 table (type Char(1)
,num1 int
,num2 int
,date1 date)
insert into #table1 (type,num1,num2,date1)
values
('a',1,2,'2019-01-01')
,('b',1,null,'2019-01-02')
,('b',3,null,'2017-05-02')
,('a',1,1,'2019-03-02')
,('a',2,3,'2018-03-15')
,('b',2,null,'2018-12-20')
select t.*,t2.date1 'Date2'
from #table1 t
inner join #table1 t2
on t.num2 = t2.num1
and t.type = 'a'
and t2.type = 'b'

Select and compare two Datetime columns from different table without having any relation

I have two Tables with below format
**Table1**
"date_Time1"
"2018-09-13 04:27:00.000"
"2018-09-13 04:28:00.000"
**Table2**
"date_Time2"
"2018-09-13 04:27:00.000"
"2018-09-13 04:29:00.000"
Now I want to comapre both these tables whether the datetime is matching or not.
The Result should like
+--------------------------+---------+
| Date_Time | Is_match|
+--------------------------+---------+
|"2018-09-13 04:27:00.000" | True |
|"2018-09-13 04:28:00.000" | False |
|"2018-09-13 04:29:00.000" | False |
+-----------------------------------+
Another possible approach, which will find duplicate dates between two tables and possible duplicate dates in each table:
WITH cte (date_time) AS (
SELECT date_time1
FROM DateTimeTable1
UNION ALL
SELECT date_time2
FROM DateTimeTable2
)
SELECT
date_time,
CASE
WHEN COUNT(*) > 1 THEN 'True'
ELSE 'False'
END AS is_match
FROM cte
GROUP BY date_time
ORDER BY date_time
You can try below query
select coalesce(t1.date_time1,t2.date_time2) as Date_Time ,
case when t1.date_time1 = t2.date_time2 then 'True' else 'False' end as Is_Match
from table1 t1 full outer join table2 t2 on t1.date_time1=t2.date_time2
Try this:
SELECT ISNULL(t1.Date_Time,t2.Date_Time) AS Date_Time,
CASE WHEN t1.Date_Time=t2.Date_Time THEN 'True' ELSE 'False' END AS Is_Match
FROM Table1 t1
OUTER JOIN Table2 t2 ON t1.Date_Time=t2.Date_Time

Taking Count of Subqueries in Full Outer Join

I am working on SQL Server 2012. My SQL follows the following structure.
SELECT A.attributeA
,A.attributeB
,Count(A.*) AS CountA -- I know this is wrong.
,Count(B.*) AS CountB
FROM
(
SELECT ... FROM Foo1
) A
FULL OUTER JOIN
(
SELECT ... FROM Foo2
) B
ON A.attribute1 = B.attribute1
GROUP BY
A.attributeA
,A.attributeB
I want to take the count of all rows from subqueries A and B. How do I do that? Thank you in advance.
Assuming the goal is to just count the non-null records from each side of the join, you can specify the column name (as mentioned in a comment) that you expect to be non-null, often the same column as in your join. For example, since you joined on attribute1:
SELECT A.attributeA
,A.attributeB
,Count(A.attribute1) AS CountA
,Count(B.attribute1) AS CountB
FROM
...
Note that this tells you nothing about when the 2 overlap, if that is part of your goal. For that type of counting, you can use a SUM combined with CASE:
SELECT A.attributeA
,A.attributeB
,Count(A.attribute1) AS CountA
,Count(B.attribute1) AS CountB
,SUM(CASE WHEN A.attribute1 IS NOT NULL AND B.attribute1 IS NOT NULL
THEN 1 ELSE 0
END) as CountAAndBOverlap
FROM
...
If your purpose is just to get the count of the two sub-queries, you can do something like this one. I've also generated common ID for the two sub-queries so that I can JOIN them.Lastly, I used INNER JOIN instead of FULL JOIN.
SELECT
CountSubqueryA AS CountA,
CountSubqueryB AS CountB
FROM
(SELECT 1 AS ID,COUNT(*) AS CountSubqueryA FROM Foo1 ) AS A
INNER JOIN
(SELECT 1 AS ID,COUNT(*) AS CountSubqueryB FROM Foo2 ) AS B
ON A.ID=B.ID
I saw your GROUP BY and thought maybe you wanted this. It will create up to 3 groups that look something like this:
==========================
| A | NOT B | 24 |
--------------------------
| NOT A | B | 31 |
--------------------------
| A | B | 69 |
==========================
SELECT
CASE WHEN A.attribute1 IS NOT NULL THEN 'A' ELSE 'NOT A' END,
CASE WHEN B.attribute1 IS NOT NULL THEN 'B' ELSE 'NOT B' END
COUNT(*)
FROM
(
SELECT ... FROM Foo1
) A
FULL OUTER JOIN
(
SELECT ... FROM Foo2
) B
ON A.attribute1 = B.attribute1
GROUP BY
CASE WHEN A.attribute1 IS NOT NULL THEN 'A' ELSE 'NOT A' END,
CASE WHEN B.attribute1 IS NOT NULL THEN 'B' ELSE 'NOT B' END

Resources