Following up from this question Possible to emulate a basic CTE in MySQL by in-lining it, would it be possible to in-line the following query in mysql5.7 without the usage of CTEs?
WITH tbl1 AS (
SELECT 1 AS a
), tbl2 AS (
SELECT 1 AS a UNION ALL SELECT 2
), tbl3 AS (
SELECT * FROM tbl1 JOIN tbl2 USING (a)
) SELECT * FROM tbl3, tbl2
If so, how could that be done?
There's no particular problem with doing that, except that you have to repeat tbl2:
SELECT *
FROM (
SELECT *
FROM (
SELECT 1 AS a
) tbl1
JOIN (
SELECT 1 AS a UNION ALL SELECT 2
) tbl2
USING (a)
) tbl3
CROSS JOIN
(
SELECT 1 AS a UNION ALL SELECT 2
) tbl2
fiddle
This would be similar to substituting the body of a function. Writing it in a similar way (conceptually speaking):
let tbl1 = (SELECT 1 AS a) AS tbl1
let tbl2 = (SELECT 1 AS a UNION ALL SELECT 2) AS tbl2
let tbl3 = (SELECT * FROM tbl1 JOIN tbl2 USING (a)) AS tbl3
-- rewriting tbl1 for tbl1 and tbl2
let tbl3 = (SELECT * FROM (SELECT 1 AS a) AS tbl1
JOIN ((SELECT 1 AS a UNION ALL SELECT 2)) AS tbl1 USING (a)) AS tbl3
SELECT * FROM tbl3, tbl2
-- substitutie for tbl3, tbl2
SELECT * FROM
(SELECT * FROM (SELECT 1 AS a) AS tbl1
JOIN ((SELECT 1 AS a UNION ALL SELECT 2)) AS tbl1 USING (a)) AS tbl3,
(SELECT 1 AS a UNION ALL SELECT 2) AS tbl2
Related
Looking for advise on the best way to approach the following
TBL1 (Local SQL DB) where ID = varchar
TBL2 (Remote MYSQL DB) where ID = INT
WITH TBL1 as (
SELECT
[Results] as 'ID'
FROM [DB].[results]
),
TBL2 as (
select * from openquery(LINKEDSERVER,'select ID, Name from DB')
)
Select
TBL1.[ID],
TBL2.[NAME]
FROM [DB]
left outer JOIN TBL1 ON TBL1.ID = TBL2.ID
Tried a couple different methods like CAST/CONVERT, but ending up with either an error like "Conversion failed when converting the varchar value '12345
' to data type int." or getting all NULLS for TBL2.
Attempted the following:
WITH TBL1 as
(
SELECT CAST(ISNULL([Results],'0') AS INT) as 'ID'
FROM [DB].[results]
),
TBL2 as ( select * from openquery(LINKEDSERVER,'select ID, Name from DB')
)
Select TBL1.[ID], TBL2.[NAME]
FROM TBL1 Left Outer join TB2 ON TBL1.ID = TBL2.ID
This results in "Conversion failed when converting the varchar value '12345
' to data type int."
Also Attempted:
WITH TBL1 as ( SELECT [Results] as 'ID' FROM [DB].[results]
),
TBL2 as ( select * from openquery(LINKEDSERVER,'select CONVERT(ID, CHAR) AS ID, Name from DB')
)
Select TBL1.[ID], TBL2.[NAME]
FROM TBL1 Left Outer join TB2 ON TBL1.ID = TBL2.ID
This results in the TBL1.ID values being displayed, but all the TBL2.Name values are NULL
Your syntax doesn't look right. Where does the DB C come from? Isn't DB the schema name?
WITH TBL1 as (
SELECT
[Results] as ID
FROM [DB].[results]
),
TBL2 as (
select * from openquery(LINKEDSERVER,'select ID, Name from DB')
)
Select
TBL1.[ID],
TBL2.[NAME]
FROM TBL2 left outer JOIN TBL1 ON try_cast(TBL1.ID as int) = TBL2.ID;
Option 1: Try converting the INT to varchar on the MySQL side of the house. Try to do it right in the sql statement you pass in to the LinkedServer.
WITH TBL1 as ( SELECT [Results] as 'ID' FROM [DB].[results]
),
TBL2 as ( select * from openquery(LINKEDSERVER,'select CONVERT(ID, CHAR) AS ID, Name from DB')
)
Select TBL1.[ID], TBL2.[NAME]
FROM TBL1 Left Outer join TB2 ON TBL1.ID = TBL2.ID
The other option is of course the reverse (if you want to join by INT)
WITH TBL1 as
(
SELECT CAST(ISNULL(TRIM([Results]),'0') AS INT) as 'ID'
FROM [DB].[results]
),
TBL2 as ( select * from openquery(LINKEDSERVER,'select ID, Name from DB')
)
Select TBL1.[ID], TBL2.[NAME]
FROM TBL1 Left Outer join TB2 ON TBL1.ID = TBL2.ID
Appreciate everyone's help. This is what got this working:
WITH TBL1 AS (
SELECT REPLACE(REPLACE(ID, CHAR(13), ''), CHAR(10), '')
FROM DB
WHERE ISNUMERIC(REPLACE(REPLACE(ID, CHAR(13), ''), CHAR(10), '')) = 1
),
TBL2 AS (
SELECT *
FROM OpenQuery(
LINKEDSERVER,
'SELECT id, name FROM DB'
)
)
SELECT
TBL1.ID
,TB2.Name
FROM TBL2
LEFT OUTER JOIN TBL1 ON TBL1.ID = TBL2.id
I have 2 identical dead-simple tables in a MySQL database with different data. I need a single query that will return all the results that aren't a duplicate.
Here's an example:
Table 1. (column "item")
a
b
c
d
Table 2. (column "item")
a
b
e
f
x
Wanted Result
c
d
e
f
x
Try this -
SELECT * FROM TABLE1 WHERE ITEM NOT IN (SELECT ITEM FROM TABLE2)
UNION
SELECT * FROM TABLE2 WHERE ITEM NOT IN (SELECT ITEM FROM TABLE1)
You can use NOT EXISTS, e.g.:
SELECT item
FROM table1 t1
WHERE NOT EXISTS (
SELECT item FROM table2 WHERE item = t1.item
);
We could join them using a distinct an union ALL. then count and having.
the distinct is needed since we care about unique accross the sets.
SELECT item FROM (
SELECT distinct item
FROM tbl1
UNION ALL
SELECT distinct item
FROM tbl2) B
GROUP BY item
HAVING count(*) =1
SELECT * FROM TABLE1 WHERE ITEM NOT IN (SELECT ITEM FROM TABLE2)
union
SELECT * FROM TABLE2 WHERE ITEM NOT IN (SELECT ITEM FROM TABLE1)
Or another method would be to use an inner join to grab all the duplicate data and then pull all the data that isn't in your duplicate dataset.
SELECT * into #temptable FROM TABLE1 INNER JOIN TABLE2 on table2.x = table1.x
union
SELECT * into #temptable FROM TABLE2 INNER JOIN TABLE1 on table2.x = table1.x
SELECT * FROM Table1 WHERE NOT IN (SELECT * FROM #temptable)
UNION
SELECT * FROM Table2 WHERE NOT IN (SELECT * FROM #temptable)
A lot like xQbert's, but with the assumption that item is UNIQUE/PRIMARY...
SELECT a.*
FROM
( SELECT item FROM table1
UNION ALL
SELECT item FROM table2
) a
GROUP
BY item
HAVING COUNT(*) = 1;
I have 5 tables. I want to get specific users in table 1 that are not in table2, table3, table4 and table5. Can someone please help me :)
table1(userid,discount)
table2(userid,discount)
table3(userid,discount)
table4(userid,discount)
table5(userid,discount)
The following query:
SELECT userid
FROM table1 AS t1
WHERE NOT EXISTS (
SELECT 1
FROM (
SELECT userid
FROM table2
UNION
SELECT userid
FROM table3
UNION
SELECT userid
FROM table4
UNION
SELECT userid
FROM table5) AS t2
WHERE t1.userid = t2.userid)
returns all users of table1 that don't exist in any of the other tables.
Demo here
If you also want, say, all users of table2 that don't exist in any of the other tables, then you can modify the above query so as to return users from table2 and perform a UNION between these two queries:
SELECT userid
FROM table1 AS t1
WHERE NOT EXISTS (
SELECT 1
FROM (
SELECT userid
FROM table2
UNION
SELECT userid
FROM table3
UNION
SELECT userid
FROM table4
UNION
SELECT userid
FROM table5) AS t2
WHERE t1.userid = t2.userid)
UNION ALL
SELECT userid
FROM table2 AS t1
WHERE NOT EXISTS (
SELECT 1
FROM (
SELECT userid
FROM table1
UNION
SELECT userid
FROM table3
UNION
SELECT userid
FROM table4
UNION
SELECT userid
FROM table5) AS t2
WHERE t1.userid = t2.userid)
Demo here
The above can easily be extended so as to incorporate users from all tables. But, I have to admit, it becomes quite verbose !
Using Microsoft Access. Is it possible to sort the ORDER BY column as Descending?
SELECT * FROM
(
SELECT table1.* FROM table1 ORDER BY table1.field1
) DUMMY_ALIAS1
UNION ALL
SELECT * FROM
(
SELECT table2.* FROM table2 ORDER BY table2.field1
) DUMMY_ALIAS2
Yes - just add desc after the field name:
SELECT * FROM
(
SELECT table1.* FROM table1 ORDER BY table1.field1 DESC
) DUMMY_ALIAS1
UNION ALL
SELECT * FROM
(
SELECT table2.* FROM table2 ORDER BY table2.field1 DESC
) DUMMY_ALIAS2
I am joining 2 tables -tbl1 and tbl2. Left join give all data from tbl1 which is in tbl2 or only on tbl1. Right join gives data from tbl2 which is don't exists in tbl1.
I want to combine both results.
What is the best way to do this so that I get all data from tbl1 and tbl2?
The only you can do that is by using UNION. MySQL doesn't support FULL JOINjust like in MSSQL.
SELECT *
FROM tbl1 t1
LEFT JOIN tbl2 t2
ON t1.col = t2.col
UNION
SELECT *
FROM tbl1 t1
RIGHT JOIN tbl2 t2
ON t1.col>= t2.<col
SEE HERE: Simulating FULL JOIN in MYSQL
By the way, UNION has optional keyword ALL,when the ALL is omitted, UNION automatically selects DISTINCT rows from the resultset.
EXAMLE:
SELECT *
FROM tableA
UNION ALL
SELECT *
FROM tableA
this can result duplicates rows
ColA ColB
==================
1 John
2 Jade
2 Jade
3 Hello
BUT if you omit the word ALL
SELECT *
FROM tableA
UNION
SELECT *
FROM tableA
this can result distinct rows only
ColA ColB
==================
1 John
2 Jade
3 Hello
What you want is FULL JOIN
LEFT JOIN + RIGHT JOIN = FULL JOIN
So try this:
SELECT * FROM tbl1
LEFT JOIN tbl2 ON tbl1.id = tbl2.id
UNION
SELECT * FROM tbl1
RIGHT JOIN tbl2 ON tbl1.id = tbl2.id
The UNION clause combines the results of two SQL queries into a single table of all matching rows.
Here's an alternative that can be easily extended if you have a full join of more than 2 tables:
SELECT t1*, t2.*
FROM
( SELECT col
FROM tbl1
UNION
SELECT col
FROM tbl2
) AS d
LEFT JOIN tbl1 AS t1
ON t1.col = d.col
LEFT JOIN tbl2 AS t2
ON t2.col = d.col ;
you have to use FULL OUTER JOIN, But mysql doesnt support it.. You could do this for getting the result:
SELECT *
FROM tbl1 t1 LEFT JOIN tbl2 t2
ON t1.<col> = t2.<col>
UNION
SELECT *
FROM tbl1 t1 RIGHT JOIN tbl2 t2
ON t1.<col>= t2.<col>