Sqlite , how select data after "case when" - sqlite

here is MyTbl1:
id (integer pk ai)
name (text char 25)
phone (int)
MyTbl2:
v1 (text char25)
v2 (text char 25)
i want make request like a:
select if exists id=1 in MyTbl1 if id=1 exists then select v1 from Mytbl2 if not exists return 0.
i try this:
select case when exists(select id from MyTbl1 where id=1) then (select v1 from MyTbl2) else 0 end;
its not working(

use where exists
Also you will get all rows from MyTbl2 if there exists a row with id =` in the Mytbl1
select v1 from MyTbl2 t2
where exists
( select 1 from MyTbl1 t1
where t2.id =1
)

This query will bring back two values: v1 and id.
But, id will be null if it is <>1 (since it will not come through the join clause)
select v1 , id
from MyTbl2 t2
left join MyTbl1 t1 on id =1
You can check if id is null and if it is, you can assume v1 is zero. This can be done as follows:
select case when id is null the 0 else v1 end
from MyTbl2 t2
left join MyTbl1 t1 on id =1

Related

I need only one unique result in Oracle sdo_nn Update sentence ,

I need Only one unique result from tableB.Field to tableA.Field
I am using sdo operator sdo_nn, this is the code:
UPDATE table1 t1
SET t1.fieldA = (SELECT T2.fieldB,SDO_NN_DISTANCE(1) distance
FROM table1 T1, table2 T2
WHERE
(sdo_nn(t1.geometry,t2.geometry,'SDO_NUM_RES=1',1)= 'TRUE')
ORDER BY DIST
)
WHERE EXISTS(
SELECT 1
FROM table2 t2
WHERE sdo_nn(t1.geometry, t2.geometry,'SDO_NUM_RES=1',1)='TRUE'
AND(t2.cell_name = 'string1' or t2.cell_name = string2')AND t1.fieldA = NULL
);
In the select sentence of the subquery i get an error because i only use one field(t1.fieldA), but in the sentence i use the operator SDO_NN_DISTANCE(1) and the sql developer count this operator like another field. What is the correct way to write this sentence? I only use sql because i need to insert this code in vba
Thanks!!!
Obviously, you can't (simplified)
set t1.fieldA = (t2.fieldB, distance) --> you want to put two values into a single column
Therefore, get fieldB alone from the subquery which uses analytic function (row_number) to "sort" rows by sdo_nn_distance(1) desc; then get the first row's fieldB value.
Something like this (I hope I set the parenthesis right):
UPDATE table1 t1
SET t1.fieldA =
(SELECT x.fieldB --> only fieldB
FROM (SELECT T2.fieldB, --> from your subquery
SDO_NN_DISTANCE (1) distance,
ROW_NUMBER ()
OVER (ORDER BY sdo_nn_distance (1) DESC) rn
FROM table1 T1, table2 T2
WHERE (sdo_nn (t1.geometry,
t2.geometry,
'SDO_NUM_RES=1',
1) = 'TRUE')) x
WHERE rn = 1) --> where RN = 1
WHERE EXISTS
(SELECT 1
FROM table2 t2
WHERE sdo_nn (t1.geometry,
t2.geometry,
'SDO_NUM_RES=1',
1) = 'TRUE'
AND ( t2.cell_name = 'string1'
OR t2.cell_name = 'string2')
AND t1.fieldA IS NULL);

SELECT SUM of each row and the next row

Table three columns id, numers1 and numbers2. We need to summarize numers1 and numbers2 but the first row to the second row numers1 numers2 the second with the third and forth etc.:
CREATE TABLE tb1 (id INTEGER PRIMARY KEY AUTOINCREMENT,numbers1,numbers2);
INSERT INTO tb1 (numbers1,numbers2) values(1,10);
INSERT INTO tb1 (numbers1,numbers2) values(2,20);
INSERT INTO tb1 (numbers1,numbers2) values(3,30);
INSERT INTO tb1 (numbers1,numbers2) values(4,40);
INSERT INTO tb1 (numbers1,numbers2) values(5,50);
I want to get as:
21
32
43
54
with the reference of getting the correct row index per record here:
How to use ROW_NUMBER in sqlite
I was able to create the required result with the following query:
SELECT
num1 + coalesce(b_num2, 0)
FROM(
SELECT
num1,
(select count(*) from test as b where a.id >= b.id) as cnt
FROM test as a) as a
LEFT JOIN
(SELECT num2 as b_num2,
(select count(*) from test as b where a.id >= b.id) as cnt
FROM test as a
) as b
ON b.cnt = a.cnt + 1
Explanation:
by joining two same table of similar record index, then merge the next record with the current record and then sum num1 of current record with num2 of next record, I do not know how you want to deal with the last row as it does not have a next row so I assume it to add nothing to have a result of just the value of num1
Result:
For one row with a specific ID x, you can get values from the next row by searching for ID values larger than x, and taking the first such row:
SELECT ...
FROM tb1
WHERE id > x
ORDER BY id
LIMIT 1;
You can then use this as a correlated subquery to get that value for each row:
SELECT numbers1 + (SELECT T2.numbers2
FROM tb1 AS T2
WHERE T2.id > T1.id
ORDER BY T2.id
LIMIT 1) AS sum
FROM tb1 AS T1
WHERE sum IS NOT NULL; -- this omits the last row, where the subquery returns NULL

Choosing Single Row from multiple rows - Teradata

I have a requirement below to choose latest status.
Table 1:
Table2:
Results Expected:
Below is the logic we need.
SELECT
Table1.ID,
,CASE WHEN (Table1.hub=Table2.hub) THEN Table2.Status ELSE NULL END AS Original_Status
,CASE WHEN (Table1.hub<>Table2.hub AND Table2.Status like 'Found%' ) THEN Table2.hub ELSE NULL END AS Derived_Hub
,CASE WHEN (Table1.hub<>Table2.hub AND Table2.Status like 'Found%' ) THEN Table2.Status ELSE NULL END AS Derived_Status
from
Table1
Join Table2
ON (Table1.ID=Table2.ID)
With this code, I am getting 3 rows. If I put max in the above case statements, I am getting Hub3 instead of Hub2.
Could you please let me know how I can merge everything into single row. Please note that I want to show latest found Status from Table 2 even if there are 2 hubs with found status.
Let me know if you need any further information.
I think your best bet is to join into Table 2 twice. The first time, much like you are doing here, but using a LEFT OUTER JOIN on both id and hub. Then the second time on a derived version of table2 where you only select the top 1 records when sorted by timestamp in descending order:
SELECT
t1.id,
t1.hub as "Original Hub"
t2.status as "Original Hub Status",
t3.hub as "Found Hub",
t3.status as "Found Hub Status"
FROM
Table1 t1
LEFT OUTER JOIN Table2 t2 ON
t1.id = t2.id AND
t1.hub = t2.hub
LEFT OUTER JOIN
(
--Select a hub with the same id, that doesn't share the same hub number
--Only choose the top record when sorted by timestamp in descending order
SELECT TOP 1 id, hub, status
FROM table2
WHERE t1.hub <> table2.hub
ORDER BY TimeStamp Desc
) t3 ON
t1.id = t3.id
That subquery that has alias t3 is using a correlated subquery by referencing the t1.hub value in it's WHERE statement.
In TD14.10 you can utilize LAST_VALUE to access data from the "last" row. The CASEs are based on your query:
SELECT
t2.ID,
CASE WHEN t1.Hub = t2.Hub THEN t2.Hub END AS Original_Hub,
CASE WHEN t1.Hub = t2.Hub THEN t2.Status END AS Original_Status,
-- get the last Hub
LAST_VALUE(CASE WHEN t1.Hub <> t2.Hub AND Table2.Status like 'Found%'
THEN t2.Hub
END)
OVER (PARTITION BY t1.ID
ORDER BY CASE WHEN t1.Hub = t2.Hub THEN 0 ELSE 1 END, t2.TS
ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS Derived_Hub,
-- get the last Status
LAST_VALUE(CASE WHEN t1.Hub <> t2.Hub AND Table2.Status like 'Found%'
THEN t2.Status
END)
OVER (PARTITION BY t1.ID
ORDER BY CASE WHEN t1.Hub = t2.Hub THEN 0 ELSE 1 END, t2.TS
ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS Derived_Status
FROM
Table1 AS t1
JOIN Table2 AS t2
ON (t1.ID=t2.ID)
QUALIFY
ROW_NUMBER () -- return the 1st row only
OVER (PARTITION BY t1.ID
ORDER BY CASE WHEN t1.Hub = t2.Hub THEN 0 ELSE 1 END, t2.TS) = 1
EXPLAIN should combine all OVER into a single STATS-step as they use the same PARTITION BY and ORDER BY.

Get the most recent record for each user where value is 'K', action id is null or its state is 1

I have the following tables in SQL Server:
user_id, value, date, action_id
----------------------------------
1 A 1/3/2012 null
1 K 1/4/2012 null
1 B 1/5/2012 null
2 X 1/3/2012 null
2 K 1/4/2012 1
3 K 1/3/2012 null
3 L 1/4/2012 2
3 K 1/5/2012 3
4 K 1/3/2012 null
action_id, state
----------------------------------
1 0
2 1
3 1
4 0
5 1
I need to return the most recent record for each user where the value is 'K', the action id is either null or its state is set to 1. Here's the result set I want:
user_id, value, date, action_id
----------------------------------
3 K 1/5/2012 3
4 K 1/3/2012 null
For user_id 1, the most recent value is B and its action id is null, so I consider this the most recent record, but it's value is not K.
For user_id 2, the most recent value is K, but action id 1 has state 0, so I fallback to X, but X is not K.
user_id 3 and 4 are straightforward.
I'm interested in Linq to SQL query in ASP.NET, but for now T-SQL is fine too.
The SQL query would be :
Select Top 1 T1.* from Table1 T1
LEFT JOIN Table2 T2
ON T1.action_id = T2.action_id
Where T1.Value = 'K' AND (T1.action_id is null or T2.state = 1)
Order by T1.date desc
LINQ Query :
var result = context.Table1.Where(T1=> T1.Value == "K"
&& (T1.action_id == null ||
context.Table2
.Where(T2=>T2.State == 1)
.Select(T2 => T2.action_id).Contains(T1.action_id)))
.OrderByDescending(T => T.date)
.FirstOrDefault();
Good Luck !!
This query will return desired result set:
SELECT
*
FROM
(
SELECT
user_id
,value
,date
,action_id
,ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY date DESC) RowNum
FROM
testtable
WHERE
value = 'K'
) testtable
WHERE
RowNum = 1
You can also try following approach if user_id and date combination is unique
Make sure to get the order of predicates in the join to be able to use indexes:
SELECT
testtable.*
FROM
(
SELECT
user_id
,MAX(date) LastDate
FROM
testtable
WHERE
value = 'K'
GROUP BY
user_id
) tblLastValue
INNER JOIN
testtable
ON
testtable.user_id = tblLastValue.user_id
AND
testtable.date = tblLastValue.LastDate
This would select the top entries for all users as described in your specification, as opposed to TOP 1 which just selects the most recent entry in the database. I'm assuming here that your tables are named users and actions:
WITH usersactions as
(SELECT
u.user_id,
u.value,
u.date,
u.action_id,
ROW NUMBER() OVER (PARTITION BY u.user_id ORDER BY u.date DESC, u.action_id DESC) as row
FROM users u
LEFT OUTER JOIN actions a ON u.action_id = a.action_id
WHERE
u.value = 'K' AND
(u.action_id IS NULL OR a.state = 1)
)
SELECT * FROM usersactions WHERE row = 1
Or if you don't want to use a CTE:
SELECT * FROM
(SELECT
u.user_id,
u.value,
u.date,
u.action_id,
ROW NUMBER() OVER (PARTITION BY u.user_id ORDER BY u.date DESC, u.action_id DESC) as row
FROM users u
LEFT OUTER JOIN actions a ON u.action_id = a.action_id
WHERE
u.value = 'K' AND
(u.action_id IS NULL OR a.state = 1)
) useractions
WHERE row = 1

Verify existence of two columns in different tables in a single SQL transaction

I'm trying to verify if data exists in two different tables in a single transaction. The reason for the single transaction is the database gets hit about 1-3 million times a day so adding anymore than 1 extra transaction would increase that number up to 9 million, and my poor little server needs a break :)
So I need to check if an ID exists in table X and table Y and return the results to my VB.net script so I can handle the outcome Ideally something like this would work
if exists (select id from X where id = #id)
print 'True,' else print 'False,'
if exists (select id from Y where id = #id)
print 'True' else print 'False'
Which gives me "True, True" if exists in both or "True, False" etc etc... But that only displays in SQL print and not actually returning it as an object/string or array values that I can use.
I'm open to any sort of solution of this nature that can give me two results from a single transaction and how to handle that response in vb. Thanks
SELECT
Case When EXISTS(SELECT 1 FROM X WHERE id = #id) Then 1 Else 0 End AS IsInX,
Case When EXISTS(SELECT 1 FROM Y WHERE id = #id) Then 1 Else 0 End AS IsInY
select (select COUNT(*) from X where id = #id) AS x_exists,
(select COUNT(*) from Y where id = #id) AS y_exists
This returns one data row with two fields, each containing either 0 or 1 (or more, if id is not unique).
CREATE PROCEDURE CheckIDOnTables(#ID int)
AS
BEGIN
DECLARE #X AS NVARCHAR(10)
DECLARE #Y AS NVARCHAR(10)
Set #X = 'False'
Set #Y = 'False'
if exists (select id from TableX where id = #ID)
Set #X = 'True'
if exists (select id from TableY where id = #ID)
Set #Y = 'True'
SELECT #X AS XExists, #Y AS YEsists
END
It will give you your desired results.

Resources