sql query- group by and then join - sql

I have 2 tables as follow:
1)passenger - with passenger_id,passenger_name and passenger_city
2)flight - with flight_id,flight_name and passenger_id.
The question is:
List the passenger details with flight id, who has travelled in more than one flight.
(This function will display the passenger details with their flight id's who has travelled in more than one flight.)
I used this query:
select * from passenger_1038299
where passengerid in(select passengerid from flight_1038299
group by passengerid
having count(passengerid)>1);
but it doesnt give me flight_ids. please tell how to retrieve flight id as well.
thanks and sorry for stupid question as new to sql.

Join the flight table to get the passenger's flights
select * from passenger_1038299 p
join flight_1038299 f on f.passenger_id = p.passenger_id
where p.passengerid in(
select passengerid from flight_1038299 group by passengerid having count(passengerid)>1
);
I like to use exists to check for multiples. With an index on passenger_id it may run faster than the query above.
select * from passenger_1038299 p
join flight_1038299 f on f.passenger_id = p.passenger_id
where exists (
select 1 from flight_1038299 f2
where f2.passenger_id = f.passenger_id
and f2.flight_id <> f.flight_id
)
Edit
Another way using the count window function:
select * from (
select *,
count() over (partition by p.passenger_id) cnt
from passenger_1038299 p
join flight_1038299 f on f.passenger_id = p.passenger_id
) t where cnt > 1

Another way with using analytic functions:
SELECT * FROM (
SELECT p.*, f.flight_id,
count(*) OVER (PARTITION BY f.passenger_id ) As number_of_flights
FROM passenger p
JOIN flight f
ON p.passenger_id = f.passenger_id
)
WHERE number_of_flights > 1
Demo: http://sqlfiddle.com/#!4/dab21/11

Try this way
Flight id should be multiple so it comma separated of column.
select a.*,b.flightid from passenger_1038299 a
join (select passengerid,Stuff((SELECT ', ' + s.flight_id
FROM flight_1038299 l
where c.passengerid = l.passengerid
FOR XML PATH('')),1,1,'') flightid from flight_1038299 as c group by c.passengerid having count(c.passengerid)>1) b on a.passengerid=b.passengerid

Related

How to fix "ABAP INNER JOIN"

i'm trying to get a inner join from two select sentences but it doesn't work, what i am doing wrong?
i cant work with internal tables because inner join doesn't permit it.
clear: it_spfli.
refresh: it_spfli.
select
spfli-cityto
spfli-cityfrom
into TABLE it_spfli from(select spfli-cityto COUNT( * )from spfli group by spfli-cityto) as t1
INNER JOIN(select spfli-cityfrom COUNT( * )from spfli group by spfli-cityfrom) as t2
ON t1-cityto = t2-cityfrom.
i expect a table of more frequency city to and city from order by city to with table spfli.
First of all i don't think you are doing the right SELECT to get what you want.
I answer this question from the technical perspective. You can use WITH.
WITH +spf1 AS (
SELECT spfli~cityto AS cityto, COUNT(*) AS count FROM spfli GROUP BY spfli~cityto ) ,
+spf2 AS (
SELECT spfli~cityfrom AS cityfrom , COUNT(*) AS count FROM spfli GROUP BY spfli~cityfrom ) ,
+spf3 AS (
SELECT s1~cityto, s2~cityfrom FROM +spf1 AS s1 INNER JOIN +spf2 AS s2
ON s1~cityto = s2~cityfrom )
SELECT * FROM +spf3 INTO TABLE #DATA(lt_result).

Count with exists in SQL

Why is this query not returning the count of the results? How do I get it to show the count
SELECT COUNT (*) AS MWith
FROM member m
JOIN Channel mc ON mc.MemberID = m.id
JOIN Client c ON c.id = m.clientid
JOIN packages p ON p.id = m.packageid
WHERE Enroll > '2018'
AND EXISTS (
SELECT * FROM
activity a
WHERE a.memberid = m.id
AND a.code IN ('785', 'a599')
)
GROUP BY m.id;
OUTPUT
MWith
1
1
1
The empty set is because of the clause group by .
The workarounds are:
Remove a GROUP BY, because m.id anyway is not part of the output
Use GROUP BY ALL
An original example:
SELECT COUNT(*) AS MWith
FROM member m
JOIN Channel mc
ON mc.MemberID = m.id
JOIN Client c
ON c.id = m.clientid
JOIN packages p
ON p.id = m.packageid
WHERE Enroll > '2018'
AND EXISTS
(
SELECT *
FROM activity a
WHERE a.memberid = m.id
AND a.code IN ( '785', 'a599' )
)
-- GROUP BY m.id;
Other, simpler examples to show a difference:
-- returns an empty resultset
SELECT COUNT(*) FROM sys.databases
WHERE 1=0
GROUP BY name
-- returns: a single row with 0
SELECT COUNT(*) FROM sys.databases
WHERE 1=0
-- Another example with GROUP BY ALL
-- it returns one row per grouped value, with expected count = 0
SELECT COUNT(*) FROM sys.databases
WHERE 1=0
GROUP BY ALL name

How to add a temp table in SQL server

I am trying to add a temp table to my query so that I can query that temp table, I have searched the internet but I couldn't get a solution.
this is my query
;WITH cte AS (
SELECT ID, g.Name
FROM game.Game g WITH(NOLOCK
WHERE ID IN (SELECT Data FROM system.Split(1, ','))
UNION ALL
SELECT g.ID, g.Name
FROM game.Game g WITH(NOLOCK)
JOIN cte ON g.ParentID = cte.ID
)
SELECT c.ID,
c.Name
FROM cte c
INNER JOIN list.Type gt WITH(NOLOCK) ON c.TypeId = gt.TypeID
WHERE c.ID NOT IN (SELECT Data FROM system.Split(1, ','))
AND c.ID IN (SELECT ID FROM game.code WITH(NOLOCK)
WHERE ID = c.ID
AND StatusCode IN ('OP', 'CL', 'SU')
AND isDisplay = 'True'
AND GETDATE() BETWEEN DisplayStart AND DisplayEnd
AND GETDATE() < ISNULL(ResultDateTime, ResultExpected)
)
which gives me the following when I run it
ID | Name
1111 | BaseBall
2222 |BasketBall
45896 |Relay
now I tried to create a temp table as follows
Create Table #temp(
ID int,
Name varchar
)
;WITH cte AS (
SELECT ID, g.Name
FROM game.Game g WITH(NOLOCK)
WHERE ID IN (SELECT Data FROM system.Split(1, ','))
UNION ALL
SELECT g.ID, g.Name
FROM game.Game g WITH(NOLOCK)
JOIN cte ON g.ParentID = cte.ID
)
insert into #temp // i wanted to set these values in the temp table
SELECT c.ID,
c.Name
FROM cte c
INNER JOIN list.Type gt WITH(NOLOCK) ON c.TypeId = gt.TypeID
WHERE c.ID NOT IN (SELECT Data FROM system.Split(1, ','))
AND c.ID IN (SELECT ID FROM game.code WITH(NOLOCK)
WHERE ID = c.ID
AND StatusCode IN ('OP', 'CL', 'SU')
AND isDisplay = 'True'
AND GETDATE() BETWEEN DisplayStart AND DisplayEnd
AND GETDATE() < ISNULL(ResultDateTime, ResultExpected)
)
every time I try to store this information in the temp table it gives me an error 'Column name or number of supplied values does not match table definition.' But I only have two values in. What am I doing wrong that I cant see?
First, why not just use select into?
IF OBJECT_ID('TempDB..#temp') IS NOT NULL
BEGIN
DROP TABLE #temp
END
select c.ID, c.Name
into #temp
from . . .
Then you don't need to define #temp as a table.
Next, your definition is bad, because Name has only one character. This would be fixed with select into.
However, I don't know why you are getting the particular error you are getting. The numbers of columns appears to match.

Alternative solution for below SQL Query ,TableMasterID NOT IN take so much time

Need alternative solution for below SQL Query ,TableMasterID NOT IN take so much time, If i remove AND TableMasterID NOT IN
(SELECT DISTINCT c.TableMasterID
FROM ComFinalDataBS as C
WHERE C.ComFileID IN
(SELECT Number FROM fn_SplitInt(#ComFileID,','))) text from below query then getting result in 20 seconds otherwise result getting arround 4 minus.
SELECT A.SubTitleId,TableMasterID from SubTitle as A JOIN ComTableMaster as B ON a.SubTitle = b.TblName AND TableMasterID NOT IN (SELECT DISTINCT c.TableMasterID
FROM ComFinalDataBS as C
WHERE C.ComFileID IN
(SELECT Number FROM fn_SplitInt(#ComFileID,','))) AND B.TableMasterID IN
(SELECT DISTINCT d.TableMasterID
FROM ComData as D
WHERE D.ComFileID IN
(SELECT Number FROM fn_SplitInt(#ComFileID,','))) ORDER BY A.MainTitleID
SELECT A.SubTitleId ,
TableMasterID
FROM SubTitle AS A
JOIN ComTableMaster AS B ON A.SubTitle = B.TblName
WHERE NOT EXISTS ( SELECT 1
FROM ComFinalDataBS C
WHERE TableMasterID = C.TableMasterID
AND C.ComFileID IN (
SELECT Number
FROM MEFCampus..fn_SplitInt(#ComFileID, ',') ) )
AND NOT EXISTS ( SELECT 1
FROM ComData D
WHERE TableMasterID = D.TableMasterID
AND D.ComFileID IN (
SELECT Number
FROM MEFCampus..fn_SplitInt(#ComFileID,
',') ) )
AND B.IsDeleted = 0
ORDER BY MainTitleID
Have you tried storing the result from the fn_split_string() into an indexed temp-table first? It should help the Query Optimizer a lot.
SELECT DISTINCT Number
INTO #ComFileID
FROM dbo.fn_SplitInt(#ComFileID,',')
CREATE UNIQUE CLUSTERED INDEX uq0_ComFileID ON #ComFileID (Number) WITH (FILLFACTOR = 100)
SELECT A.SubTitleId,TableMasterID
FROM SubTitle as A
JOIN ComTableMaster as B
ON a.SubTitle = b.TblName
/*
AND B.TableMasterID NOT IN (SELECT DISTINCT c.TableMasterID
FROM ComFinalDataBS as C
JOIN #ComFileID CFI
ON CFI.Number = C.ComFileID )
*/
AND NOT EXISTS ( SELECT *
FROM ComFinalDataBS as C
JOIN #ComFileID CFI
ON CFI.Number = C.ComFileID
WHERE c.TableMasterID = B.TableMasterID )
/*
AND B.TableMasterID IN (SELECT DISTINCT d.TableMasterID
FROM ComData as D
JOIN #ComFileID CFI
ON CFI.Number = D.ComFileID
*/
AND EXISTS ( SELECT *
FROM ComData as D
JOIN #ComFileID CFI
ON CFI.Number = D.ComFileID
WHERE D.TableMasterID = B.TableMasterID )
ORDER BY A.MainTitleID

SQL - UNION, priority on the first select statement when doing order by

I'm trying to print out the results from the "GermanDB" Database first, while also showing everything from the Boston DB that was not in the German database. Can this be done in one query?
My query (the bold part functions but does not order the way I want)
select * from (
SELECT DISTINCT a.ProductRef
FROM GERMANDB.dbo.LOCATIONS AS a INNER JOIN GERMANDB.dbo.ITEMS AS b ON a.ProductRef = b.ProductRef
WHERE b.ACTIVE=1
) ta
UNION select * from
SELECT DISTINCT c.ProductRef
FROM BOSTONDB.dbo.LOCATIONS AS c INNER JOIN BOSTONDB.dbo.ITEMS AS d ON c.ProductRef = d.ProductRef
WHERE c.ACTIVE=1 (c.ProductRef NOT IN
(SELECT ProductRef FROM GERMANDB.dbo.ITEMS where ACTIVE=1))
) tb
order by ta.ProductRef** , tb.productRef
Just add one field to signal the priority. Like this:
select *, 0 as Priority from (
SELECT DISTINCT a.ProductRef
FROM GERMANDB.dbo.LOCATIONS AS a INNER JOIN GERMANDB.dbo.ITEMS AS b ON a.ProductRef = b.ProductRef
WHERE b.ACTIVE=1
) ta
UNION select *, 1 as Priority from
SELECT DISTINCT c.ProductRef
FROM BOSTONDB.dbo.LOCATIONS AS c INNER JOIN BOSTONDB.dbo.ITEMS AS d ON c.ProductRef = d.ProductRef
WHERE c.ACTIVE=1 (c.ProductRef NOT IN
(SELECT ProductRef FROM GERMANDB.dbo.ITEMS where ACTIVE=1))
) tb
order by Priority, ProductRef