In our databases we have crewmembers and non-crewmembers. Each crewmeber and non-crewmember can have friends.
for example a crewmember is befriended with 4 crewmembers and 2 non-crewmembers.
What I would like to know is the avarage number of non-crewmembers our crewmembers with AirlineCode=LH have.
We have two tables involved:
AppUser: where the user data are stored.
Here we have the Cells
AppUser.IsCrew (0 = non-crewmembers and 1 = crewmember)
AppUser.AirlineCode (sting of some sort)
Follower: Friends list stored
Follower.FromUserId
Follower.ToUserId
There we store that AppUser.Id = 1 has 5 friends and follows Follower.ToUserId 3,4,5 and so on
Problem here is and I don't even know how to start:
Query which checks
a) All AppUser.IsCrew=1 and has Airline.Code=LH
b) Check in Follower table how many users they follow but only the ToUserId who are in AppUser.IsCrew have = 0
And somehow return a average number
Thanks a lot for the help
First, you'll need to count how many non-crewmembers friends each crewmember person has. Make sure you also count all crewmembers even if they don't have any friend.
Then it's a matter of averaging those counts. The query should look like:
with x as (
select
c.id, count(n.id) as nc_total
from AppUser c
left join Follower f on f.FromUserId = c.id
left join AppUser n on f.ToUserId = n.id and n.isCrew = 0
where c.isCrew = 1
and c.AirLineCode = 'LH'
group by c.id
)
select avg(nc_total) from x
Related
Can anyone help to create a SQL code which could list movies which have been searched under 2 or more tags for the tables below? E.g. I want to list all movies which have the tags “4star” AND “Drama”.
Tables
I have managed to create one which lists movies which have either one or another tag… thus.
Select tblMovies.MovieName
FROM tblMovies, tblBridge, tblTags
WHERE ((tblTags.TagID=1) OR (tblTags.TagID=5))
And tblTags.TagID = tblBridge.TagID
And tblBridge.MediaID= tblMovies.MovieID
Which gives Star Wars, Aliens, Goodfellows, Mermaids.
But I'm struggling with the AND code which would give Goodfellows and The Godfather if I search for movies which have tags 1 (4star) and 7 (Drama) for example.
Many thanks.
You are looking for movies for which exist both tags 1 and 7. We don't use joins usually when we only want to check whether data exists. We use EXISTS. Or IN, which expresses the same thing (movies that are in the set of tag 1 movies and also in the set of tag 7 movies).
The idea is that we select FROM the table we want to see results from. And we use the WHERE clause to tell the DBMS which rows we want to see.
With EXISTS
SELECT m.moviename
FROM tblmovies m
WHERE EXISTS (SELECT null FROM tblbridge b WHERE b.tagid = 1 AND b.movieid = m.movieid)
AND EXISTS (SELECT null FROM tblbridge b WHERE b.tagid = 7 AND b.movieid = m.movieid)
ORDER BY m.moviename;
With IN
SELECT m.moviename
FROM tblmovies m
WHERE m.movieid IN (SELECT b.movieid FROM tblbridge b WHERE b.tagid = 1)
AND m.movieid IN (SELECT b.movieid FROM tblbridge b WHERE b.tagid = 7)
ORDER BY m.moviename;
I should add that these are not the only options available to get that result. But they are the straight-forward ones. (Another is conditional aggregation, but you'll learn this later.)
I have the following data in table VehiclesAccSummary:
I am not sure how to do this but what I want is a query that would return all rows where there where only two car in the accident and it was a head on crash so in both cars PointOfImpact was 'Front' i know in need to do some inner join on the same table but i don' want to join same car with it self. Any idea ?
The end result should be something like this
You can use a subquery to count the number of "Front' records for each AccRef.
SELECT *
FROM VehiclesAccSummary INNER JOIN
(SELECT VehiclesAccSummary.AccRef, Count(VehiclesAccSummary.PointOfImpact) AS CountOfPointOfImpact FROM VehiclesAccSummary GROUP BY VehiclesAccSummary.AccRef, VehiclesAccSummary.PointOfImpact HAVING VehiclesAccSummary.PointOfImpact="Front") AS FrontCount
ON VehiclesAccSummary.AccRef = FrontCount.AccRef
WHERE VehiclesAccSummary.NumCars = 2 AND CountOfPointOfImpact = 2;
This will limit the records to AccRefs with NumCar = 2 and the count of Front records = 2.
Edit: Since the same car can be listed in multiple records, we need a new approach. Try this:
SELECT VehiclesAccSummary.*, Subquery.CountOfPointOfImpact
FROM VehiclesAccSummary LEFT JOIN (SELECT VehiclesAccSummary.AccRef, Count(VehiclesAccSummary.PointOfImpact) AS CountOfPointOfImpact
FROM VehiclesAccSummary
WHERE (((VehiclesAccSummary.PointOfImpact)<>"Front"))
GROUP BY VehiclesAccSummary.AccRef) AS Subquery ON VehiclesAccSummary.AccRef = Subquery.AccRef
WHERE (((Subquery.CountOfPointOfImpact) Is Null));
Instead of confirming that the count of front accidents is 2, this confirms that the count of non-front accidents is 0.
I have one main table and join other tables via left outer or right outer outer join.One row of main table have over 30 row in join query as result. And I try pagination. But the problem is I can not know how many rows will it return for one main table row result.
Example :
Main table first row result is in my query 40 rows.
Main table second row result is 120 row.
Problem(Question) UPDATE:
For pagination I need give the pagesize the count of select result. But I can not know the right count for my select result. Example I give page no 1 and pagesize 50, because of this I cant get the right result.I need give the right pagesize for my main table top 10 result. Maybe for top 10 row will the result row count 200 but my page size is 50 this is the problem.
I am using Sql 2014. I need it for my ASP.NET project but is not important.
Sample UPDATE :
it is like searching an hotel for booking. Your main table is hotel table. And the another things are (mediatable)images, (mediatable)videos, (placetable)location and maybe (commenttable)comments they are more than one rows and have one to many relationship for the hotel. For one hotel the result will like 100, 50 or 10 rows for this all info. And I am trying to paginate this hotels result. I need get always 20 or 30 or 50 hotels for performance in my project.
Sample Query UPDATE :
SELECT
*
FROM
KisiselCoach KC
JOIN WorkPlace WP
ON KC.KisiselCoachId = WP.WorkPlaceOwnerId
JOIN Album A
ON KC.KisiselCoachId = A.AlbumId
JOIN Media M
ON A.AlbumId = M.AlbumId
LEFT JOIN Rating R
ON KC.KisiselCoachId = R.OylananId
JOIN FrUser Fr
ON KC.CoachId = Fr.UserId
JOIN UserJob UJ
ON KC.KisiselCoachId = UJ.UserJobOwnerId
JOIN Job J
ON UJ.JobId = J.JobId
JOIN UserExpertise UserEx
ON KC.KisiselCoachId = UserEx.UserExpertiseOwnerId
JOIN Expertise Ex
ON UserEx.ExpertiseId = Ex.ExpertiseId
Hotel Table :
HotelId HotelName
1 Barcelona
2 Berlin
Media Table :
MediaID MediaUrl HotelId
1 www.xxx.com 1
2 www.xxx.com 1
3 www.xxx.com 1
4 www.xxx.com 1
Location Table :
LocationId Adress HotelId
1 xyz, Berlin 1
2 xyz, Nice 1
3 xyz, Sevilla 1
4 xyz, Barcelona 1
Comment Table :
CommentId Comment HotelId
1 you are cool 1
2 you are great 1
3 you are bad 1
4 hmm you are okey 1
This is only sample! I have 9999999 hotels in my database. Imagine a hotel maybe it has 100 images maybe zero. I can not know this. And I need get 20 hotels in my result(pagination). But 20 hotels means 1000 rows maybe or 100 rows.
First, your query is poorly written for readability flow / relationship of tables. I have updated and indented to try and show how/where tables related in hierarchical relativity.
You also want to paginate, lets get back to that. Are you intending to show every record as a possible item, or did you intend to show a "parent" level set of data... Ex so you have only one instance per Media, Per User, or whatever, then once that entry is selected you would show details for that one entity? if so, I would do a query of DISTINCT at the top-level, or at least grab the few columns with a count(*) of child records it has to show at the next level.
Also, mixing inner, left and right joins can be confusing. Typically a right-join means you want the records from the right-table of the join. Could this be rewritten to have all required tables to the left, and non-required being left-join TO the secondary table?
Clarification of all these relationships would definitely help along with the context you are trying to get out of the pagination. I'll check for comments, but if lengthy, I would edit your original post question with additional details vs a long comment.
Here is my SOMEWHAT clarified query rewritten to what I THINK the relationships are within your database. Notice my indentations showing where table A -> B -> C -> D for readability. All of these are (INNER) JOINs indicating they all must have a match between all respective tables. If some things are NOT always there, they would be changed to LEFT JOINs
SELECT
*
FROM
KisiselCoach KC
JOIN WorkPlace WP
ON KC.KisiselCoachId = WP.WorkPlaceOwnerId
JOIN Album A
ON KC.KisiselCoachId = A.AlbumId
JOIN Media M
ON A.AlbumId = M.AlbumId
LEFT JOIN Rating R
ON KC.KisiselCoachId = R.OylananId
JOIN FrUser Fr
ON KC.CoachId = Fr.UserId
JOIN UserJob UJ
ON KC.KisiselCoachId = UJ.UserJobOwnerId
JOIN Job J
ON UJ.JobId = J.JobId
JOIN UserExpertise UserEx
ON KC.KisiselCoachId = UserEx.UserExpertiseOwnerId
JOIN Expertise Ex
ON UserEx.ExpertiseId = Ex.ExpertiseId
Readability of a query is a BIG help for yourself, and/or anyone assisting or following you. By not having the "on" clauses near the corresponding joins can be very confusing to follow.
Also, which is your PRIMARY table where the rest are lookup reference tables.
ADDITION PER COMMENT
Ok, so I updated a query which appears to have no context to the sample data and what you want in your post. That said, I would start with a list of hotels only and a count(*) of things per hotel so you can give SOME indication of how much stuff you have in detail. Something like
select
H.HotelID,
H.HotelName,
coalesce( MedSum.recs, 0 ) as MediaItems,
coalesce( LocSum.recs, 0 ) as NumberOfLocations,
coalesce( ComSum.recs, 0 ) as NumberOfLocations
from
Hotel H
LEFT JOIN
( select M.HotelID,
count(*) recs
from Media M
group by M.HotelID ) MedSum
on H.HotelID = MedSum.HotelID
LEFT JOIN
( select L.HotelID,
count(*) recs
from Location L
group by L.HotelID ) LocSum
on H.HotelID = LocSum.HotelID
LEFT JOIN
( select C.HotelID,
count(*) recs
from Comment C
group by C.HotelID ) ComSum
on H.HotelID = ComSum.HotelID
order by
H.HotelName
--- apply any limit per pagination
Now this will return every hotel at a top-level and the total count of things per the hotel per the individual counts which may or not exist hence each sub-check is a LEFT-JOIN. Expose a page of 20 different hotels. Now, as soon as one person picks a single hotel, you can then drill-into the locations, media and comments per that one hotel.
Now, although this COULD work, having to do these counts on an every-time query might get very time consuming. You might want to add counter columns to your main hotel table representing such counts as being performed here. Then, via some nightly process, you could re-update the counts ONCE to get them primed across all history, then update counts only for those hotels that have new activity since entered the date prior. Not like you are going to have 1,000,000 posts of new images, new locations, new comments in a day, but of 22,000, then those are the only hotel records you would re-update counts for. Each incremental cycle would be short based on only the newest entries added. For the web, having some pre-aggregate counts, sums, etc is a big time saver where practical.
I know there are a lot of other SO entries that seem like this one, but I haven't found one that actually answers my question so hopefully one of you can either answer it or point me to another SO question that is related.
Basically, I have the following query that returns Venues that have any CheckIns that contain the searched Keyword ("foobar" in this example).
SELECT DISTINCT v.*
FROM "venues" v
INNER JOIN "check_ins" c ON c."venue_id" = v."id"
INNER JOIN "keywordings" ks ON ks."check_in_id" = c."id"
INNER JOIN "keywords" k ON ks."keyword_id" = k."id"
WHERE (k."name" = 'foobar')
I want to SELECT and ORDER BY the count of the matched Keyword for each given Venue. E.g. if there have been 5 CheckIns that have been created, associated with that Keyword, then there should be a returned column (called something like keyword_count) with the value 5 which is sorted.
Ideally this should be done without any queries in the SELECT clause, or preferably none at all.
I've been struggling with this for a while and my mind is just going blank (perhaps it's been too long a day) so some help would be greatly appreciated here.
Thanks in advance!
Sounds like you need something like:
SELECT v.x, v.y, count(*) AS keyword_count
FROM "venues" v
INNER JOIN "check_ins" c ON c."venue_id" = v."id"
INNER JOIN "keywordings" ks ON ks."check_in_id" = c."id"
INNER JOIN "keywords" k ON ks."keyword_id" = k."id"
WHERE (k."name" = 'foobar')
GROUP BY v.x, v.y
ORDER BY 3
I have two tables.
USER user_id password
FRIEND_LIST user_id friend_id
If user 1 is friend of user 2 then in friend_list there will be 2 records:
1 2
2 1
Thats how I'm controlling friend list.
My question is how can I create an efficient query that validates if a user is a friend of a friend.
For example user 1 has in his friend list user 2. and user 3 has in his friend list user 2. So user 2 is a common friend of both 1 and 3.
Here is how friend_list table looks like:
1 2
2 1
3 2
2 3
No I want to know if user 1 has a friend that has as friend user 3.
The pseudocode is as follows:
validate(){
valid = false
list = get all friends from user 1 and store them in 'list'.
for each friend in list {
list2 = get all friends from friend
for each friend2 in list2 {
if friend2.user_id = 3 }
valid = true
break; //stop here because we have found that 3 is a friend of a friend of 1
}
}
}
return valid
}
This is how it would look like in a programming language. Now I want to validate the same but just with an SQL query.
I tried this but I dont know if this is a good way to validate that.
select *
from friend_list fl1
inner join friend_list fl2 on fl1.user_id = fl2.user_id
inner join friend_list fl3 on fl2.friend_id = fl3.user_id
where fl1.user_id = 1 and fl3.friend_id = 3
Thanks in advance.
Thank you very much for your support. This is the first time I use this forum
and helped me a lot.
I used the EXISTS code you posted like this.
SELECT EXISTS (
SELECT
*
FROM
friend_list AS users
INNER JOIN
friend_list AS friends
ON users.friend_id = friends.user_id
WHERE
users.user_id = 1
AND friends.friend_id = 3
) AS result
As you're looking to find out if there are Any instances of "a and b have a friend in common" you're better of using the EXISTS keyword.
The benefit of this over using COUNT or DISTINT is that the optimiser knows a couple of things:
1. The actual data doesn't matter
2. It can stop searching after the first hit
For example...
IF EXISTS (
SELECT
*
FROM
friend_list AS [user]
INNER JOIN
friend_list AS [friend]
ON [user].friend_id = [friend].user_id
WHERE
[user].user_id = #user_id
AND [friend].friend_id = #friend_of_friend_id
)
BEGIN
RETURN 1
-- Or whatever code you want to execute
END
ELSE
BEGIN
RETURN 0
-- Or whatever code you want to execute
END
Although this doesn't have "TOP 1" and uses "*", it neither actually returns multiple fields or rows. It literally just searches for the existance of a match and stops when it finds one.
The query you already wrote is along the right lines, I think you need one less join to the friend-list table:
select distinct fl1.user_id, fl2.friend_id
from friend_list fl1
inner join friend_list fl2 on fl1.friend_id = fl2.user_id
where fl1.user_id = 1 and fl2.friend_id = 3
So '1' (fl1.user_id) is friends with 'x' (fl1.friend_id and fl2.user_id) who is friends with '3' (fl2.friend_id).
Because you have two complementary entries in friend-list for each pair of friends, the query is nice and simple. It would be a bit tougher if each pair of friends only got one row in friend-list ....
(edit: realised too many joins were happening...)
(edit: added a distinct into the select after comment conversation)