sql creating table from columns in other tables - sql

I have 4 tables called table1, table2, table3, table4. Each has a column in it called x,y,z, and w respectively:
x y z w
--- ------ ------ ----
1 A 120 Red
2 B 33.3 Orange
3 C 81.3 Green
4 D 41.3 Blue
I would like to create a new table that simply has it its columns, just these columns where the order of the rows are unchanged. In R(), I would just do something like data.frame(x,y,z,w), but, I don't know how to do something equivalent in SQL Server 2016. The tables have no common key (except their row number of course!).

you can use something like this:
WITH CTE_Table1 AS (
SELECT x, ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS x_row
FROM Table1
), CTE_Table2 AS (
SELECT y, ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS y_row
FROM Table2
), CTE_Table3 AS (
SELECT z, ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS z_row
FROM Table3
), CTE_Table4 AS (
SELECT w, ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS w_row
FROM Table4
)
SELECT x, y, z, w
FROM CTE_Table1
INNER JOIN CTE_Table2 ON CTE_Table1.x_row = CTE_Table2.y_row
INNER JOIN CTE_Table3 ON CTE_Table1.x_row = CTE_Table3.z_row
INNER JOIN CTE_Table4 ON CTE_Table1.x_row = CTE_Table4.w_row

Related

How to select groups which has only the values we want and not select it if it also has other values in SQL

id
code
value
A
cod
2
A
buy
34
A
cod
4
B
cod
44
B
F
23
C
thk
45
C
cod
33
C
F
31
D
cod
22
In this table for example, I want those groups of id which has 'code' column value as ONLY cod or F. so query should return values of id = B and nothing else. ( Not even values with id = C because id=C also has 'thk' in code , not even id= D, and output should have ids with ONLY the mentioned two values)
expected output
id
code
value
B
cod
44
B
F
23
You want all rows for the ID of which not exists a forbidden row:
select id, code, value
from mytable
where not exists
(
select null
from mytable forbidden_row
where forbidden_row.id = mytable.id
and forbidden_row.code not in ('cod', 'F')
);
One of approaches with nested query
SELECT ID,Code, value FROM (
select ID, Code,
(SELECT count(*) FROM TableA a where Code = 'cod' and a.ID = TableA.ID) Cod,
(SELECT count(*) FROM TableA a where Code = 'F' and a.ID = TableA.ID) F,
(SELECT count(*) FROM TableA a where Code not in ('F','cod') and a.ID = TableA.ID) Other,
Value
from TableA
) SOURCE
WHERE Cod <> 0 AND F <> 0 and Other = 0
We can achieve this using CTE. Check this,
-- Split the two record category first, then check cod Or F condition.
WITH Count2 AS (
SELECT id
FROM YourTable
GROUP BY id
HAVING COUNT(id) = 2
),
codORF AS (
SELECT id, code, COUNT(id) FROM YourTable T1
LEFT JOIN Count2 T2 On T1.id = T2.id
WHERE code = 'cod' OR code = 'F'
GROUP BY id, code
Having COUNT(id) = 1
)
-- Finally to take all values
SELECT T1.*
FROM YourTable T1
INNER JOIN codORF T2 ON T1.id = T2.id
with main as (
select *, count(id) over(partition by id order by id) as total_rows
from sample
), next_and_before as (
select *,
COALESCE(lag(code) over(partition by id order by id),lead(code) over(partition by id order by id)) as before_next
from main where total_rows <= 2
)
select * from next_and_before
where lower(trim(concat(code,before_next)))in('codf','fcod','cod','f')
Its a bit of hacky solution:
first you are filtering out all the rows that have less than or equal to 2 rows, since there could be cases where you only have one row per id with a code value = 'f' or 'cod', if you don't want that then simply change the last part to: in ('codf','fcod')
then out of two rows, you are looking at the next and before value and checking if it contains other than 'f' or 'cod'
where clause will filter those out if they exist
Test Results from the link below:
Results of sample data

How can I display two columns together in SQL?

I have 2 queries that return data in the form:
query 1:
column 1
a
b
c
query 2:
column 2
d
e
How can I combine the 2 queries to get output as:
column 1 column 2
a d
b e
c
The order of data in the columns does not matter.
Possibly anything with joins ?
Thanks
use row_number()
select t1.col1,t2.col2 from
(
select *,row_number() over(order by col1) rn from query1
) t1 full outer join
(
select *,row_number() over(order by col2) rn from query2
) t2 on t1.rn=t2.rn
For n,m rows use full outer join
A possible solution is selecting both columns with row_number() and join them by the row_number. One must be aware to select first from the table with the higher number of rows. Example:
select
col_1,
col_2
from (
select
a.col_1,
row_number() over () rn
from a
) s1
FULL OUTER JOIN (
select
b.col_2,
row_number() over () rn
from b
) s2 on s1.rn = s2.rn

2 equals select expression within select

I have to process my data by Levenshtein function.
In this case I'm using nested selection
SELECT levenshtein(a.param, b.param), *
FROM (
SELECT 5 fields
FROM table t,
JOIN x,
JOIN y,
GROUP BY 1, 2, 3
) a,
FROM (
SELECT 5 fields
FROM table t,
JOIN x,
JOIN y,
GROUP BY 1, 2, 3
) b,
is there a way to not duplicate inner SELECT ?
Solution is pretty simple, thanks to #Nikarus for suggestion about WITH expression:
WITH subtable AS (
SELECT 5 fields
FROM table t,
JOIN x,
JOIN y,
GROUP BY 1, 2, 3
)
SELECT levenshtein(a.param, b.param), *
FROM subtable a, subtable b

In sql, can you join to a select statement that references the outer tables in other joins?

What I want to do is to transform the following sql
SELECT X
FROM Y LEFT JOIN Z ON Y.Id=Z.id
WHERE Y.Fld='P'
into
SELECT Y
FROM Y LEFT JOIN (SELECT TOP 1 Id FROM Z WHERE Z.Id=Y.Id ORDER BY Z.PrimaryKey DESC) ON 1=1
WHERE Y.Fld='P'
The reason I want to do this is because Z has multiple rows that can be joined to Y, that are not unique in a distinguishable way, other than that the one we need is the latest one, and we only need that one record. Is this possible? I tried it but mssql complained that I cannot reference Y.Id from within the sub query.
How about a CTE approach:
;WITH CTE
AS
(
SELECT Id,
PrimaryKey,
ROW_NUMBER() OVER (PARTITION BY Id, ORDER BY Primarykey Desc) AS RN
FROM Z
)
SELECT X
FROM Y
LEFT JOIN CTE
ON CTE.ID = Y.ID
WHERE CTE.RN = 1

Is it possible to join two tables of multiple rows by only the first ID in each table?

Let's say I have two tables of data:
Table A
ID Colors
-- ------
1 Blue
1 Green
1 Red
Table B
ID States
-- ------
1 MD
1 VA
1 WY
1 CA
Is it possible to join these tables so that I get the following instead of 12 rows?
ID Colors States
-- ------ ------
1 Blue MD
1 Green VA
1 Red WY
1 CA
There's no association between the colors and states columns and the order of the columns doesn't matter. (e.g. Blue can be next to MD, VA, WY, or CA) The number of items in each column (Colors or States) per ID is not equal.
Thanks.
You can do this by using row_number() to create a fake join column:
select coalesce(a.id, b.id) as id, a.colors, b.states
from (select a.*, row_number() over (order by id) as seqnum
from a
) a full outer join
(select b.*, row_number() over (order by id) as seqnum
from b
) b
on b.seqnum = a.seqnum
Actually, in Oracle, you can also just use rownum:
select coalesce(a.id, b.id) as id, a.colors, b.states
from (select a.*, rownum as seqnum
from a
) a full outer join
(select b.*, rownum as seqnum
from b
) b
on b.seqnum = a.seqnum
You can also use a CTE (Common Table Expression) Like so:
WITH TableA (ID, Color) AS
(
SELECT "ID", Color
FROM DatabaseName.TableA
)
, Joined AS (
SELECT
a.ID AS "AID",
a.Color
b.ID AS "BID",
b."State"
FROM,
TableA AS a
RIGHT OUTER JOIN DatabaseName.TableB AS b ON a.ID = b.ID
)
SELECT
AID,
Color,
State
FROM
Joined