I need to combine 2 results from SELECT statements that look in the same table.
What I have works but I'm sure there is a better way to do it.
SELECT
games._id,win.winner,deal.dealer
FROM
games,
(SELECT
players.name as winner
FROM
games, players
WHERE
players._id = games.winner
AND games._id = 2) AS win,
(SELECT
players.name as dealer
FROM
games, players
WHERE
players._id = games.dealer
AND games._id = 2) AS deal
WHERE
games._id = 2
Thanks for your help optimizing this query.
EDIT:
The schema for the tables are:
CREATE TABLE games
(
_id INTEGER PRIMARY KEY,
winner integer,
dealer integer
)
CREATE TABLE players
(
_id INTEGER PRIMARY KEY,
name text
)
Something like below(untested code) should work:
SELECT g._id,p1.name AS winner,p2.name AS dealer
FROM games AS g join players AS p1 ON p1._id = g.winner
JOIN players AS p2 on p2._id = g.dealer
WHERE g._id = 2
Related
I have been stuck on this progressive question for more than 10 days now
Questions is :: Find all the actors that made more movies with Yash Chopra than any other director
Heres my attempt
SELECT pidsWhoDidMoviesWithYashChopra.pid,
pidsWhoDidMoviesWithYashChopra.moviesWithYashChopra,
pidsOfThoseWhoDidMoviesWithDirectors.moviesByAPID,
pidsWhoDidMoviesWithYashChopra.countOfMoviesWithYashChopraByAPID,
pidsOfThoseWhoDidMoviesWithDirectors.totalNumberOfMoviesByAPID
FROM
(
SELECT TRIM(M_Cast.PID) AS pid, moviesByYashChopra.mDirectorMID AS moviesWithYashChopra, COUNT(moviesByYashChopra.mDirectorMID) AS countOfMoviesWithYashChopraByAPID
FROM M_Cast
JOIN
(
SELECT TRIM(M_Director.MID) AS mDirectorMID
FROM
M_Director
WHERE TRIM(M_Director.PID) IN
(
SELECT TRIM(Person.PID) AS personPID
FROM
Person
WHERE Person.Name LIKE '%Yash Chopra%'
)
) AS moviesByYashChopra
ON TRIM(M_Cast.MID) == moviesByYashChopra.mDirectorMID
GROUP BY pid
) AS pidsWhoDidMoviesWithYashChopra
JOIN
(
SELECT TRIM(M_Cast.PID) AS pid, TRIM(M_Cast.MID) AS moviesByAPID, COUNT(TRIM(M_Cast.MID)) AS totalNumberOfMoviesByAPID
FROM M_Cast
GROUP BY pid
) AS pidsOfThoseWhoDidMoviesWithDirectors
ON pidsWhoDidMoviesWithYashChopra.pid == pidsOfThoseWhoDidMoviesWithDirectors.pid
GROUP BY pidsWhoDidMoviesWithYashChopra.pid
And here's the output it produces
And here's the schema
Now where I require help is :: Ability to go ahead from here :: As in how do i dissect this part of the question "than any other director." :: I think that's the tricky part
Any direction/hints will be helpful, Thanks...
You need to join person (for the actor's details) with m_cast, movie, m_director and person again (for the director's details) and group by actor and director to count the number of movies each actor made with each director.
Then use window functions first_value() to get the name of the director with whom the actor made the most movies and lag() to get the 2nd max number of movies (this is needed to filter out ties).
Enclose this query inside a CTE and then filter:
with cte as (
select pa.pid, pa.name, count(*) counter,
first_value(pd.name) over (partition by pa.pid, pa.name order by count(*) desc) max_dir_name,
lag(count(*)) over (partition by pa.pid, pa.name order by count(*) desc) prev_counter
from person pa
inner join m_cast c on c.pid = pa.pid
inner join movie m on m.mid = c.mid
inner join m_director d on d.mid = m.mid
inner join person pd on pd.pid = d.pid
group by pa.pid, pa.name, pd.name
)
select pid, name, counter
from cte
where max_dir_name = 'Yash Chopra' and coalesce(prev_counter, 0) < counter
I'm trying to replace a placeholder string inside a selection of 10 random records with a random string (a name) taken from another table, using only sqlite statements.
i've done a subquery in order to replace() of the placeholder with the results of a subquery. I thought that each subquery loaded a random name from the names table, but i've found that it's not the case and each placeholder is replaced with the same string.
select id, (replace (snippet, "%NAME%", (select
name from names
where gender = "male"
) )
) as snippet
from imagedata
where timestamp is not NULL
order by random()
limit 10
I was expecting for each row of the SELECT to have different random replacement every time the subquery is invoked.
hello i'm %NAME% and this is my house
This is the car of %NAME%, let me know what you think
instead each row has the same kind of replacement:
hello i'm david and this is my house
This is the car of david, let me know what you think
and so on...
I'm not sure it can be done inside sqlite or if i have to do it in php over two different database queries.
Thanks in advance!
Seems that random() in the subquery is only evaluated once.
Try this:
select
i.id,
replace(i.snippet, '%NAME%', n.name) snippet
from (
select
id,
snippet,
abs(random()) % (select count(*) from names where gender = 'male') + 1 num
from imagedata
where timestamp is not NULL
order by random() limit 10
) i inner join (
select
n.name,
(select count(*) from names where name < n.name and gender = 'male') + 1 num
from names n
where gender = 'male'
) n on n.num = i.num
I have a query that Counts 2 columns from 2 separate tables using subqueries, which works. Now I have to implement into this query the ability to filter out these results based on the Date of a Call Record. I will post the query in which I am working with:
SELECT (m.FirstName || " " || m.LastName) AS Members,
(
SELECT count(CallToLineOfficers.MemberID)
FROM CallToLineOfficers
WHERE CallToLineOfficers.MemberID = m.MemberID
)
+ (
SELECT count(CallToMembers.MemberID)
FROM CallToMembers
WHERE CallToMembers.MemberID = m.MemberID
) AS Tally
FROM Members AS m, Call, CallToMembers, CallToLineOfficers
Join Call on CallToMembers.CallID = Call.CallID
and CallToLineOfficers.CallID = Call.CallI
WHERE m.FirstName <> 'None'
-- and Call.Date between '2017-03-21' and '2017-03-22'
GROUP BY m.MemberID
ORDER BY m.LastName ASC;
Ok, so table Call stores the Date and its PK is CallID. Both CallToLineOfficers and CallToMembers are Bridge Tables that also contain only CallID and MemberID. With the current query, where the Date is commented out, that Date range should only return all names, but a count of 1 should appear under 1 person's name.
I have tried joining Call.CallID with both Bridge Tables' CallIDs without any luck, though I think this is the right way to do it. Could someone help point me in the right direction? I am lost. (I tried explaining this the best I could, so if you need more info, let me know.)
UPDATED: Here is a screenshot of what I am getting:
Based on the provided date in the sample, the new results, with the Date, should be:
Bob Clark - 1
Rob Catalano - 1
Matt Butler - 1
Danielle Davidson - 1
Jerry Chuska - 1
Tom Cramer - 1
Everyone else should be 0.
At the moment, the subqueries filter only on the member ID. So for any member ID in the outer query, they return the full count.
To reduce the count, you have to filter in the subqueries:
SELECT (FirstName || " " || LastName) AS Members,
(
SELECT count(*)
FROM CallToLineOfficers
JOIN Call USING (CallID)
WHERE MemberID = m.MemberID
AND Date BETWEEN '2017-03-21' AND '2017-03-22'
)
+ (
SELECT count(*)
FROM CallToMembers
JOIN Call USING (CallID)
WHERE MemberID = m.MemberID
AND Date BETWEEN '2017-03-21' AND '2017-03-22'
) AS Tally
FROM Members AS m
WHERE FirstName <> 'None'
ORDER BY LastName ASC;
I have following two tables:
CREATE TABLE messages (
id integer UNIQUE NOT NULL,
message text,
recipient integer NOT NULL,
sender integer NOT NULL,
sent_at text NOT NULL,
FOREIGN KEY (recipient) REFERENCES users (id),
FOREIGN KEY (sender) REFERENCES users (id)
);
CREATE TABLE users (
id integer UNIQUE NOT NULL,
username text NOT NULL,
);
I need a very specific query, that looks like the following:
SELECT *
FROM messages
WHERE sender = 123 OR recipient = 123
ORDER BY id desc
LIMIT 1
I need to kind of iterate over the messages table, using every user, and putting him in the WHERE statement.
-- TABLE 'users':
-- 123 = id of user1
-- 456 = id of user2
-- 789 = id of user3
Is it possible to iterate in SQLite?
Goal is, to get the newest "conversation" for every user in the users table. For every user, the newest message involving him should be displayed, no matter if that newest message was sent or recieved by him.
You could use a correlated subquery to get that value for each user ID:
SELECT id,
username,
(SELECT MAX(id)
FROM messages
WHERE sender = users.id
OR recipient = users.id
) AS last_message_id
FROM users
This is also possible with GROUP BY.
First join the two table together, then create a group for each user:
SELECT users.id,
MAX(messages.id)
FROM users
JOIN messages ON users.id = messages.sender OR
users.id = messages.recipient
GROUP BY users.id
SELECT year , COUNT(*) AS Count
FROM Movie
WHERE Movie.MID NOT IN
(SELECT DISTINCT m.MID
FROM Movie m
JOIN M_Cast m_c ON m.MID = m_c.MID
JOIN Person p_1 ON m_c.PID = p_1.PID
AND p_1.Gender='Male')
AND Movie.MID IN
(SELECT DISTINCT m.MID
FROM Movie m
JOIN M_Cast m_c ON m.MID = m_c.MID
JOIN Person p_1 ON m_c.PID = p_1.PID
AND p_1.Gender='Female')
GROUP BY year;
I have 3 Data Table Claim, Part and Labor.
In this Claim is parent table and Part and Labor is mapping tables of Claim and they have Part and Labor has the ClaimId as a Foreign Key.
Claim has data like:
Part has data Like
Labor table has data Like
Target Output would be:
Can anyone help me to achieve this in SQL server.
I have tried to solve with the Union/CTE but it did not gives the result as I want.
I got the same output (for your updated output screen) for this specific case. I don't know if any other data will work for you.
SELECT TMP.ClaimId
, CASE WHEN TMP.RowNum = 1 THEN TMP.Name ELSE NULL END AS ClaimName
, CASE WHEN TMP.RowNum = 1 THEN TMP.Note ELSE NULL END AS Note
, TMP.PartId
, TMP.PartNumber
, TMP.PartCost
, JOIN_L.LaborId
, JOIN_L.LaborCost
FROM (
SELECT C.ClaimId, C.Name, C.Note, P.PartId, P.PartNumber, P.PartCost
, ROW_NUMBER() OVER(PARTITION BY C.ClaimId ORDER BY P.PartId) AS RowNum
FROM Claim AS C
LEFT JOIN Part AS P ON C.ClaimId = P.ClaimId
)AS TMP
LEFT JOIN (
SELECT *
, ROW_NUMBER() OVER(PARTITION BY L.ClaimId ORDER BY L.ClaimId) AS RowNum
FROM Labor AS L
) AS JOIN_L ON (TMP.ClaimId = JOIN_L.ClaimId AND TMP.RowNum = JOIN_L.RowNum)
ORDER BY TMP.ClaimId
Not sure why you tried CTE here
Select C.ClaimId,C.name,C.Note,P.PartId,P.PartNumber,P.PartCost,L.LabourId,L.LabourCost
From Claim C
Left Outer Join Part P On P.ClaimId = C.ClaimId
Left Outer Join Labor L On L.ClaimId=C.ClaimId