SQL to search and delete with several keycolumns - sql

A bit bad title maybe but I try to explain what I mean.
I use SQL like this to build a list
SELECT id
FROM parcel
WHERE id IN (113715, 113824, 113855, 113954, 114010, 114116, 114272, 114329)
where ID is a column in parcel table that is quarantined to be unique, very straightforward.
But some tables use many columns to be unique.
SELECT id1, id2
FROM trip
WHERE id1, id2 IN ((113715, 113824), (113855, 113954), (114010, 114116),(114272, 114329))
The last SQL is obviously not working.
I want to select rows where
id1 = 113715 and id2=113824 or
id1 = 113855 and id2=113954 or
id1 = 114010 and id2=114116 or
id1 = 114272 and id2=114329
In reality the generated SQL can contain 500 - 1000 ids.
What SQL should I use ?
EDIT
This is a generated SQL. The ID's come from another database on another server so JOIN for example is not possible.

SELECT id1, id2 FROM trip
INTERSECT
select id1, id2 from (values (113715,113824),(113855,113954),(114010,114116),(114272,114329)) a(id1,id2)
USE INTERSECT

You could use a join with a values list:
SELECT id1, id2
FROM trip
INNER JOIN (VALUES (113715,113824),(113855,113954),(114010,114116),(114272,114329)) V(a, b)
ON id1 = a
AND id2 = b

Can you use the generated ids like this?
;WITH GenerateIds AS
(
SELECT * FROM (VALUES
-- Paste the Id list below
(113715,113824),(113855,113954),(114010,114116),(114272,114329)
) t(id1, id2)
)
-- Use inner join
SELECT id1, id2 FROM trip INNER JOIN GenerateIds g ON
trip.id1 = g.id1 AND trip.id2 = g.id2

Unfortunately SQL Server doesn't support tuples in IN like
SELECT id1, id2
FROM trip
WHERE (id1,id2) in ((113715,113824),(113855,113954),(114010,114116),(114272,114329));
which is valid in some other DBMS.
So you can either follow your own suggestion
SELECT id1, id2
FROM trip
WHERE (id1 = 113715 and id2 = 113824)
OR (id1 = 113855 and id2 = 113954)
OR (id1 = 114010 and id2 = 114116)
...;
Or use a temporary table, cte or the like. Easiest might be to join a values clause:
SELECT trip.id1, trip.id2
FROM trip
JOIN (VALUES (113715,113824),(113855,113954),(114010,114116),(114272,114329))
AS src(id1, id2) ON src.id1 = trip.id1 AND src.id2 = trip.id2;

Another Simple Query:
SELECT id1, id2
FROM trip
WHERE 1 = 1
AND ((id1 = 113715 and id2=113824)
OR (id1 = 113855 and id2=113954)
OR (id1 = 114010 and id2=114116) OR (id1 = 114272 and id2=114329))

Related

UPDATE statement in SQLite with nested FROM and JOIN

I currently have an SQL statment:
UPDATE table_1 SET
property_1=b.value_1,
property_2=b.value_2,
property_3=b.value_3
FROM (
SELECT a.property_4, a.property_5, b.value_2, b.value_3
FROM (
SELECT id1 AS property_4, MAX(id2) AS property_5
FROM table_2
WHERE
id1 IN (...) AND
id2 NOT IN (...)
) a
JOIN table_3 b ON
a.property_5 = b.id
) a
WHERE
table_1.id = a.property_4
which works fine on our production postgresql db, however the syntax for UPDATE is different in SQLite (what we use in test) and I am finding my self quite stuck as to how to convert it. The error I receive is Error: syntax error near FROM. If anyone is a SQLite whiz I would greatly appreciate some guidance.
Since SQLite doesn't support UPDATE with JOIN/FROM clause. You can use CTE & SubQuery to do it alternatively:
WITH cte AS (
SELECT a.property_4, b.value_1, b.value_2, b.value_3
FROM (
SELECT id1 AS property_4, MAX(id2) AS property_5
FROM table_2
WHERE
id1 IN (...) AND
id2 NOT IN (...)
) a
JOIN table_3 b ON
a.property_5 = b.id
)
UPDATE table_1 SET
property_1=(select value_1 from cte where cte.property_4 = id)
property_2=(select value_2 from cte where cte.property_4 = id)
property_3=(select value_3 from cte where cte.property_4 = id)
WHERE
id IN (select property_4 from cte)

Chaining joins in SQL based on dynamic table

The title may not be accurate for the question but here goes! I have the following table:
id1 id2 status
1 2 a
2 3 b
3 4 c
6 7 d
7 8 e
8 9 f
9 10 g
I would like to get the first id1 and last status based on a dynamic chain joining, meaning that the result table will be:
id final_status
1 c
6 g
Logically, I want to construct the following arrays based on joining the table to itself:
id1 chained_ids chained_status
1 [2,3,4] [a,b,c]
6 [7,8,9,10] [d,e,f,g]
Then grab the last element of the chained_status list.
Since if we were to keep joining this table to itself on id1 = id2 we would eventually have single rows with these results. The problem is that the number of joins is not constant (a single id may be chained many or few times). There is always a 1 to 1 mapping of id1 to id2.
Thanks in advanced! This can be done in either T-SQL or Hive (if someone has a clever map-reduce solution).
You can do this with a recursive CTE:
;WITH My_CTE AS
(
SELECT
id1,
id2,
status,
1 AS lvl
FROM
My_Table T1
WHERE
NOT EXISTS
(
SELECT *
FROM My_Table T2
WHERE T2.id2 = T1.id1
)
UNION ALL
SELECT
CTE.id1,
T3.id2,
T3.status,
CTE.lvl + 1
FROM
My_CTE CTE
INNER JOIN My_Table T3 ON T3.id1 = CTE.id2
)
SELECT
CTE.id1,
CTE.status
FROM
My_CTE CTE
INNER JOIN (SELECT id1, MAX(lvl) AS max_lvl FROM My_CTE GROUP BY id1) M ON
M.id1 = CTE.id1 AND
M.max_lvl = CTE.lvl

How to list multiple field matches from a single table in oracle SQL

I have the following table:
create table Likes(ID1 number(5), ID2 number(5));
insert into Likes values(1689, 1709);
insert into Likes values(1709, 1689);
insert into Likes values(1782, 1709);
insert into Likes values(1911, 1247);
insert into Likes values(1247, 1468);
insert into Likes values(1641, 1468);
insert into Likes values(1316, 1304);
insert into Likes values(1501, 1934);
insert into Likes values(1934, 1501);
insert into Likes values(1025, 1101);
The table contains the 'likes' of users identified by their IDs. Liking is a one way connection (If ID1 likes ID2 does not mean that TD2 is liking ID1).
I want to find those IDs, where is a two way connection (where the 'liker' is 'liked back' by user he likes).
I am beginner with Oracle SQL, I hope my question isn't that banal...
You can do it with a join:
SELECT t.id1,t.id2
FROM Likes t
INNER JOIN Likes s
ON(t.id1 = s.id2 and t.id2 = s.id1)
Or with EXISTS()
SELECT t.*
FROM Likes t
WHERE EXISTS(select 1 FROM Likes s
WHERE t.id1 = s.id2
AND t.id2 = s.id1)
try this:
with tab as (select id1, id2 from Likes)
select id1, id2 from tab
intersect
select id2, id1 from tab;
It should perform better, becuase it'll read Likes table only once
Use this query:
SELECT
id1, id2 from Likes L1
INNER JOIN (
Select id1, id2 from Likes
) as L2
on (L1.id1 = L2.id)
WHERE L1.id2 = L2.id1
You need to pick a given record id1=X, id2=Y only in a case when another record exists in the table, which has id1=Y, id2=X.
A condition like this can be expressed in SQL with the help of EXISTS operator and a dependent subquery:
SELECT *
FROM likes t
WHERE EXISTS (
SELECT 1 FROM likes t1
WHERE t.id1 = t1.id2 AND t.id2 = t1.id1
)

SQL combine two tables into one table and add a new column

I need to combine two tables into one. Ans also, add a column (assign an int value) to the new table on SQL. So that the rows from table1 and ones from table2 are assigned with different values.
Example,
table1
ID1 ID2 ID3 VALUE
table2
ID1 ID2 ID3 VALUE
table3
ID1 ID2 ID3 VALUE
i need to combine table3 and table2 into a new table and add a new column
table_new
top_id ID2 ID3 VALUE
It is Netezza SQL.
INSERT INTO new_table
SELECT *
FROM
(
SELECT * , **sum (table1.VALUE * table2.VALUE) AS new_value**
FROM table1
JOIN
table2
ON table1.id1 = table2.id1
GROUP BY table2.id2, table2.id3
) AS tt_a # here, I need to add a new column to tt, call it as top_id and also assign an int
# value to it, such as 80
UNION ALL
SELECT *
FROM
(
SELECT * , **sum (table1.VALUE * table3.VALUE) AS new_value**
FROM table1
JOIN
table3
ON table1.id1 = table3.id1
GROUP BY table3.id2, table3.id3
) AS tt_b # here, I need to add a new column to tt, call it as top_id and also assign an
# int value to it, such as 81
**ORDER BY top_id**
I got error:
I em new to SQL.
ERROR [HY000] ERROR: 0 : Functionality not implemented
Any help would be appreciated.
It's not entirely clear what you want, but I'm going to assume it's a UNION ALL example.
UNION ALL will combine the result sets of 2 or more SELECT statements. It returns all rows from each select statement (even if the row exists in more than one of the SELECT statements) as 1 result set.
example:
select '81' as top_id,id2,id3 from T1 group by id2,id3
UNION ALL
select '79' as top_id,id3,id400 from T1 group by id3, id400
UNION ALL
SELECT '80' as top_id,id2,id3
FROM table1
JOIN
table2
ON table1.id1 = table2.id1
GROUP BY table1.id2, table2.id3
;
Each select statement (this example combines 3) should be a valid query all by itself and should return the same amount of columns with the same datatypes.
reference: http://www.techonthenet.com/sql/union_all.php

LINQ join from 3 differents tables

I have 3 tables
T1: id1, col1 (id1 is primary key)
T2: id2, id1, col2 (id1 here is external key from T1)
T3: id3, id1, col3 (id external key of T1)
My question is simple: how do I get a join list of all the columns of the 3 tables using LINQ?
I figure out how to join results of several tables, this is an example, you can join as many tables as wished.
var a = (from s in _DBEntities.Services
join d in _DBEntities.Departements on s.se_id_departement equals d.id_departement
join i in _DBEntities.SsCategoriesServices on s.se_id_sscategorieService equals i.id_SsCategorieService
select new Services
{
IdService = s.id_service,
Adresse = s.adresseService,
NomSousCategory = i.libelleSsCategorieService,
NomDepartement = d.nom,
}).ToList();