combine two select query - sql

I have two select query like
select name1,age1 from table1
output :
+--------+------+
| name1 | age1 |
+--------+------+
| ravi | 25 |
| rakhav | 12 |
| joil | 10 |
+--------+------+
select color,no from table2
output
+--------+----+
| color | no |
+--------+----+
| red | 3 |
| yellow | 4 |
+--------+----+
i want the output like
+--------+------+--------+----+
| name1 | age1 | color | no |
+--------+------+--------+----+
| ravi | 25 | red | 3 |
| rakhav | 12 | yellow | 4 |
| joil | 10 | | |
+--------+------+--------+----+

Try this:
select * from
(select name1, age1, row_number() over(order by age1 desc) as rn from table1) as t1
left join
(select color, no, row_number() over(order by no) as rn from table2) as t2
on t1.rn = t2.rn

try select t1.*, t2.* from table1 t1, table2 t2

Related

SELECT DISTINCT on multiple columns with new value

I have these two tables.
Table #1:
+----+------+-----+
| ID | Y | AGE |
+----+------+-----+
| 1 | 2022 | a |
| 1 | 2022 | b |
| 3 | 2021 | a |
| 4 | 2021 | a |
| 4 | 2021 | b |
| 4 | 2021 | c |
| 7 | 2021 | a |
| 7 | 2022 | b |
+----+-------+----+
Table #2:
+----+------+-----------+
| ID | num | something |
+----+------+-----------+
| 1 | 10 | a1221 |
| 3 | 30 | a4342 |
| 4 | 40 | bdssd |
| 7 | 70 | asdsds |
+----+-----+------------+
and I would like to merge them into this result set:
+----+-------+-----+
| ID | Y | num |
+----+-------+-----+
| 1 | 2022 | 10 |
| 3 | 2021 | 30 |
| 4 | 2021 | 40 |
| 7 | 2021 | 70 |
| 7 | 2022 | 70 |
+----+-------+-----+
That means I would like take unique pairs of T1.ID and T1.Y ignoring column AGE and them INNER JOIN resulting table with T2 on T1.ID = T2.ID.
I know I can do this in steps as
WITH cte AS
(
SELECT ID, Y
FROM T1
GROUP BY ID, Y
)
SELECT cte.ID, cte.Y, T2.num
FROM cte
INNER JOIN T2 ON cte.ID = T2.ID
but is there any better way without creating a temporary table? Because simple
SELECT T1.ID, T1.Y, T2.num
FROM T1
INNER JOIN T2 ON T1.ID = T2.ID
will result with duplicates that comes from T1.AGE even tho I'm not using it
I think it's better to use views for this:
CREATE VIEW dbo.view1
AS
SELECT
ID
,Y
FROM T1
GROUP BY ID
,Y
GO
And call it wherever needed like tables:
SELECT v1.ID, v1.Y, T2.num
FROM view1 v1
INNER JOIN T2 ON v1.ID = T2.ID

Show All Duplicate Records QUERY

What is the query that will show all the records that have multiple names?
For example.
Table 1:
| ID | Name | Age | Email |
+----+---------+-------+-----------------+
| 1 | Mike | 12 | mike#gmail.com |
| 2 | Mon | 10 | mon#gmail.com |
| 3 | Peter | 12 | pet#gmail.com |
| 4 | Mike | 13 | mike12#gmail.com|
Desired result:
| ID | Name | Age | Email |
+----+---------+-------+-----------------+
| 1 | Mike | 12 | mike#gmail.com |
| 4 | Mike | 13 | mike12#gmail.com|
One option, using COUNT() as an analytic function:
WITH cte AS (
SELECT t.*, COUNT(*) OVER (PARTITION BY Name) cnt
FROM yourTable t
)
SELECT ID, Name, Age, Email
FROM cte
WHERE cnt > 1;
You can use GROUP BY and join result to origin table
SELECT t1.*
FROM myTable t1
JOIN
(SELECT Name
FROM myTable
GROUP BY Name
HAVING COUNT(Name) > 1) t2
ON t1.Name = t2.Name

Greatest-n-per-group query including rows that don't have 'n'

I know that this is a common question but I haven't been able to find an answer to this specific problem:
I have two tables:
+--------------+ +-------------------------------+
| temp1 | | temp2 |
+----+---------+ +----+----+---------------------+
| id | name | | id | fk | ts |
+----+---------+ +----+--------------------------+
| 1 | first | | 1 | 1 | 2020-06-19 23:56:46 |
| 2 | second | | 2 | 1 | 2020-06-19 22:56:46 |
| 3 | third | | 3 | 2 | 2020-06-19 21:56:46 |
+----+---------+ | 4 | 2 | 2020-06-19 20:56:46 |
+----+--------------------------+
In order to get for each entry in temp1 the corresponding entry from temp2 with the newest timestamp I am running the following query:
SELECT
t1.id AS id,
t1.name AS name,
t2.ts AS ts
FROM
(temp2 t2
JOIN temp1 t1)
WHERE
t2.ts = (SELECT MAX(t3.ts)
FROM
temp2 t3
WHERE
t2.fk = t3.fk)
AND t2.fk = t1.id
This results in:
+----+--------+---------------------+
| id | name | ts |
+----+------------------------------+
| 1 | first | 2020-06-19 23:56:46 |
| 2 | second | 2020-06-19 21:56:46 |
+----+------------------------------+
Is it possible to alter this query in order to include the rows from temp1 that do not have a corresponding value in temp2?
The desired result would be:
+----+--------+---------------------+
| id | name | ts |
+----+------------------------------+
| 1 | first | 2020-06-19 23:56:46 |
| 2 | second | 2020-06-19 21:56:46 |
| 3 | third | NULL |
+----+------------------------------+
Use window functions:
SELECT t1.id, t1.name, t2.ts
FROM t1 LEFT JOIN
(SELECT t2.*, ROW_NUMBER() OVER (PARTITION BY t2.fk ORDER BY t2.ts DESC) as seqnum
FROM temp2 t2
) t2
ON t2.fk = t1.id AND seqnum = 1;
The simplest way to do this is with a correlated subquery in the SELECT list:
SELECT t1.*,
(SELECT MAX(t2.ts) FROM temp2 t2 WHERE t2.fk = t1.id) ts
FROM temp1 t1
See the demo.
Results:
| id | name | ts |
| --- | ------ | ------------------- |
| 1 | first | 2020-06-19 23:56:46 |
| 2 | second | 2020-06-19 21:56:46 |
| 3 | third | |

Hive window functions: last value of previous partition

Using Hive window functions, I would like to get the last value of the previous partition:
| name | rank | type |
| one | 1 | T1 |
| two | 2 | T2 |
| thr | 3 | T2 |
| fou | 4 | T1 |
| fiv | 5 | T2 |
| six | 6 | T2 |
| sev | 7 | T2 |
Following query:
SELECT
name,
rank,
first_value(rank over(partition by type order by rank)) as new_rank
FROM my_table
Would give:
| name | rank | type | new_rank |
| one | 1 | T1 | 1 |
| two | 2 | T2 | 2 |
| thr | 3 | T2 | 2 |
| fou | 4 | T1 | 4 |
| fiv | 5 | T2 | 5 |
| six | 6 | T2 | 5 |
| sev | 7 | T2 | 5 |
But what I need is "the last value of the previous partition":
| name | rank | type | new_rank |
| one | 1 | T1 | NULL |
| two | 2 | T2 | 1 |
| thr | 3 | T2 | 1 |
| fou | 4 | T1 | 3 |
| fiv | 5 | T2 | 4 |
| six | 6 | T2 | 4 |
| sev | 7 | T2 | 4 |
This seems quite tricky. This is a variant of group-and-islands. Here is the idea:
Identify the "islands" where type is the same (using difference of row numbers).
Then use lag() to introduce the previous rank into the island.
Do a min scan to get the new rank that you want.
So:
with gi as (
select t.*,
(seqnum - seqnum_t) as grp
from (select t.*,
row_number() over (partition by type order by rank) as seqnum_t,
row_number() over (order by rank) as seqnum
from t
) t
),
gi2 as (
select gi.*, lag(rank) over (order by gi.rank) as prev_rank
from gi
)
select gi2.*,
min(prev_rank) over (partition by type, grp) as new_rank
from gi2
order by rank;
Here is a SQL Fiddle (albeit using Postgres).

Unmatched rows with values from both tables

I have two tables T1:
+----+-----+--------------------+----------+
| ID | emp | manager | proj |
+----+-----+--------------------+----------+
| 1 | Sam | Tom | aa |
| 1 | Sam | Tom | bb |
| 1 | Sam | Tom | cc |
| 1 | Sam | Tom | dd |
+----+-----+--------------------+----------+
Table T2:
+--------+---------+--------+-----------+
| Course | Type | proj | Category |
+--------+---------+--------+-----------+
| XYZ | NEW | aa | a |
| DWE | OLD | bb | b |
| RTY | OLD | ii | c |
| UIO | NEW | gg | d |
+--------+---------+--------+-----------+
OUTPUT:
+-----------+-----+----------+--------+---------+---------+----------+
| ID | emp | manager | proj | Course | Type | Category |
+-----------+-----+----------+--------+---------+---------+----------+
| 1 | Sam | Tom | ii | RTY | OLD | c |
| 1 | Sam | Tom | gg | UIO | NEW | d |
+-----------+-----+----------+--------+---------+---------+----------+
I have one common col proj, table 1 has the proj done by the emp, table2 has both proj done and not done by emp with additional fields. I want to get all the unmatched rows from table2 but with the attributes from table 1 as above. Can someone help with a SQL query to do this??
Try this
with a as (
select T2.* from T1 right join T2
on T1.proj=T2.proj
where T1.proj is null) ,
b as (select T1.id, T1.emp, t1.manager from T1 left join T2
on T1.proj=T2.proj
group by T1.id, T1.emp, t1.manager,T2.proj
having T2.proj is null)
select * from a cross join b
select e.ID, e.emp, e.manager, t2.proj, t2.Course, t2.Type as Name, t2.Category
from t2
cross join (select distinct ID, emp, manager from T1) e
where not exists(select * from t1 where t1.prog=t2.proj)
SELECT tbl.ID, tbl.emp, tbl.manager, t2.proj, t2.Course, t2.Type as Name, t2.Category
FROM
(
SELECT t2.ID, t2.emp, t2.manager
FROM Table2 t2
WHERE NOT EXISTS (SELECT 1 FROM Table1 t1 WHERE t1.proj = t2.proj)
) tbl
CROSS APPLY Table1 t1