Am I looking for a cross join? - sql

If I have two tables:
id_table entry_table
-------- -----------
[Id] [entries]
1 a
2 b
3 c
4 d
5
Is there a way to select the results into another table where I get:
select_results
--------------
[Id] [entries]
1 a
2 b
3 c
I'm trying e.g.
Select top 3 * from id_table, entry_table
and vice versa, but that gives:
1 a
1 b
1 c
These two tables SHOULD have the same amount of entries but I'm using "top 3" at the minute to see if it's possible.
Maybe I need a cross join with a where clause?

you can use row_number() and then use join
select a.*,b.* from
(select *,row_number() over(order by Id) rn1
from id_table
) a
join
(select *,row_number() over(order by entries) rn1
from entry_table
) b on a.rn=b.rn1

Alternatively you can use row_number() window analytic function with top keyword as
select top 3
[Id], [entries]
from id_table i
join ( select row_number() over (order by [entries]) as row_id,
[entries]
from entry_table ) e
on i.[Id]=e.row_id;
Demo

Related

Reorder the rows of a table according to the numbers of similar cells in a specific column using SQL

I have a table like this:
D
S
2
1
2
3
4
2
4
3
4
5
6
1
in which the code of symptoms(S) of three diseases(D) are shown. I want to rearrange this table (D-S) such that the diseases with more symptoms come up i.e. order it by decreasing the numbers of symptoms as below:
D
S
4
2
4
3
4
5
2
1
2
3
6
1
Can anyone help me to write a SQL code for it in SQL server?
I had tried to do this as the following but this doesn't work:
SELECT *
FROM (
select D, Count(S) cnt
from [D-S]
group by D
) Q
order by Q.cnt desc
select
D,
S
from
D-S
order by
count(*) over(partition by D) desc,
D,
S;
Two easy ways to approach this:
--==== Sample Data
DECLARE #t TABLE (D INT, S INT);
INSERT #t VALUES(2,1),(2,3),(4,2),(4,3),(4,5),(6,1);
--==== Using Window Function
SELECT t.D, t.S
FROM (SELECT t.*, Rnk = COUNT(*) OVER (PARTITION BY t.D) FROM #t AS t) AS t
ORDER BY t.Rnk DESC;
--==== Using standard GROUP BY
SELECT t.*
FROM #t AS t
JOIN
(
SELECT t2.D, Cnt = COUNT(*)
FROM #t AS t2
GROUP BY t2.D
) AS t2 ON t.D = t2.D
ORDER BY t2.Cnt DESC;
Results:
D S
----------- -----------
4 2
4 3
4 5
2 1
2 3
6 1

how to write a SQL to display distinct values of two columns in one row

I have tables a,b.
Table a
ID In
----------------
1 Mat1
1 Mat2
2 Mat1
3 Mat3
Table b
ID Out
--------------
1 Mat4
2 Mat4
2 Mat5
3 Mat6
I want a result like below.
ID In Out
------------------
1 Mat1 Mat4
1 Mat1
2 Mat1 Mat4
2 Mat5
3 Mat3 Mat6
I think full join can't make empty field in some row.Maybe I need to use Rownum for this? Any help? Thx.
One option is to use row_number() to enumerate the rows, and then full join the results. For this to really make sense, you would need a column in each table to order the records. I assumed ordering_id:
select id, a.in, b.out
from (
select a.*, row_number() over(partition by id order by ordering_id) rn
from tablea a
) a
full join (
select b.*, row_number() over(partition by id order by ordering_id) rn
from tableb b
) b using(id, rn)
Not all database support full joins (and not all of them support using() for join conditions).
A more portable approach is to use union all:
select id, max(in) in, max(out) out
from (
select id, in, null out, row_number() over(partition by id order by ordering_id) rn
from tablea
union all
select id, null, out, row_number() over(partition by id order by ordering_id) rn
from tableb b
) x
group by id, rn

SQL select top if columns are same

If I have a table like this:
Id StateId Name
1 1 a
2 2 b
3 1 c
4 1 d
5 3 e
6 2 f
I want to select like below:
Id StateId Name
4 1 d
5 3 e
6 2 f
For example, Ids 1,3,4 have stateid 1. So select row with max Id, i.e, 4.
; WITH CTE AS
(
SELECT *, ROW_NUMBER() OVER(PARTITION BY STATEID ORDER BY ID DESC) AS RN
)SELECT ID, STATEID, NAME FROM CTE WHERE RN = 1
You can use ROW_NUMBER() + TOP 1 WITH TIES:
SELECT TOP 1 WITH TIES
Id,
StateId,
[Name]
FROM YourTable
ORDER BY ROW_NUMBER() OVER (PARTITION BY StateId ORDER BY Id DESC)
Output:
Id StateId Name
4 1 d
6 2 f
5 3 e
Disclaimer: I gave this answer before the OP had specified an actual database, and hence avoided using window functions. For a possibly more appropriate answer, see the reply by #Tanjim above.
Here is an option using joins which should work across most RDBMS.
SELECT t1.*
FROM yourTable t1
INNER JOIN
(
SELECT StateId, MAX(Id) AS Id
FROM yourTable
GROUP BY StateId
) t2
ON t1.StateId = t2.StateId AND
t1.Id = t2.Id
The following using a subquery, to find the maximum Id for each of the states. The WHERE clause then only includes rows with ids from that subquery.
SELECT
[Id], [StateID], [Name]
FROM
TABLENAME S1
WHERE
Id IN (SELECT MAX(Id) FROM TABLENAME S2 WHERE S2.StateID = S1.StateID)

Find the Row count of each value

I have table like
Name
A
B
B
C
C
C
A
A
B
B
I need Query to return output like
Name count
A 1
B 2
C 3
A 2
B 2
I tried with rank(),dense_Rank().but i am not able to get output
In order to group the names and get the counts of names in every separated group, a simple count function with a group by or window functions does not solve your problem, I prefer to use two helper fields one for row number, the other holds a value for group number, you'll iterate through your table and increase the value of group field for the next name if it's not the same as current:
Assuming your table is:
create table tblN (Name varchar(10))
insert into tblN values
('A'),
('B'),
('B'),
('C'),
('C'),
('C'),
('A'),
('A'),
('B'),
('B');
following query is for above explanation:
;with cte1 as(
select 1 gp,name -- add gp for group number
from tblN
),
cte2 as(
select gp,name,
row_number() over(order by gp) rn --add rn for evaluating groups
from cte1
),
cte3 as(
select gp,name,rn from cte2 where rn=1
union all
select case --evaluate groups
when c2.name=c3.name then c3.gp
else c3.gp+1
end gp,
c2.name,c2.rn
from cte3 c3
join cte2 c2 on c3.rn+1=c2.rn
)
select gp,name from cte3 --[1]
Result:
gp name
1 A
2 B
2 B
3 C
3 C
3 C
4 A
4 A
5 B
5 B
now in above query instead of line [1] just use below query:
select name , count from(
select top 1000 gp,name,
count(name) count
from cte3
group by gp,name
order by gp) q
Result:
name count
A 1
B 2
C 3
A 2
B 2
you can achieve your requirement very easy with following query
SELECT * FROM (SELECT ROW_NUMBER() OVER(PARTITION BY NAME ORDER BY NAME) AS COUNT,NAME FROM TABLENAME )T ORDER BY 1,2

left join without duplicate values using MIN()

I have a table_1:
id custno
1 1
2 2
3 3
and a table_2:
id custno qty descr
1 1 10 a
2 1 7 b
3 2 4 c
4 3 7 d
5 1 5 e
6 1 5 f
When I run this query to show the minimum order quantities from every customer:
SELECT DISTINCT table_1.custno,table_2.qty,table_2.descr
FROM table_1
LEFT OUTER JOIN table_2
ON table_1.custno = table_2.custno AND qty = (SELECT MIN(qty) FROM table_2
WHERE table_2.custno = table_1.custno )
Then I get this result:
custno qty descr
1 5 e
1 5 f
2 4 c
3 7 d
Customer 1 appears twice each time with the same minimum qty (& a different description) but I only want to see customer 1 appear once. I don't care if that is the record with 'e' as a description or 'f' as a description.
First of all... I'm not sure why you need to include table_1 in the queries to begin with:
select custno, min(qty) as min_qty
from table_2
group by custno;
But just in case there is other information that you need that wasn't included in the question:
select table_1.custno, ifnull(min(qty),0) as min_qty
from table_1
left outer join table_2
on table_1.custno = table_2.custno
group by table_1.custno;
"Generic" SQL way:
SELECT table_1.custno,table_2.qty,table_2.descr
FROM table_1, table_2
WHERE table_2.id = (SELECT TOP 1 id
FROM table_2
WHERE custno = table_1.custno
ORDER BY qty )
SQL 2008 way (probably faster):
SELECT custno, qty, descr
FROM
(SELECT
custno,
qty,
descr,
ROW_NUMBER() OVER (PARTITION BY custno ORDER BY qty) RowNum
FROM table_2
) A
WHERE RowNum = 1
If you use SQL-Server you could use ROW_NUMBER and a CTE:
WITH CTE AS
(
SELECT table_1.custno,table_2.qty,table_2.descr,
RN = ROW_NUMBER() OVER ( PARTITION BY table_1.custno
Order By table_2.qty ASC)
FROM table_1
LEFT OUTER JOIN table_2
ON table_1.custno = table_2.custno
)
SELECT custno, qty,descr
FROM CTE
WHERE RN = 1
Demolink