table name : users u
id username src
1 mark 101
2 stanley 102
3 john 103
4 stewe 104
table name : call_history c
id src dst duration
1 101 555-1217 20
2 555-1315 102 30
3 555-2245 102 40
4 102 555-6523 30
5 102 555-4213 20
6 555-1689 102 15
7 103 555-1775 35
There are two tables and these columns.
Conditions are;
SUM(duration) AS OutboundSUM (Condition: u.src=c.src )
COUNT(duration) AS OutboundCNT (Condition: u.src=c.src )
SUM(duration) AS InboundSUM (Condition: u.src=c.dst )
COUNT(duration) AS InboundCNT (Condition: u.src=c.dst )
What I need to see with Group By per username;
username OutboundSUM OutboundCNT InboundSUM InboundCNT
mark 20 1 0 0
stanley 50 2 85 3
john 35 1 0 0
stewe 0 0 0 0
I tried UNION ALL, sub query after select, INNER JOIN but It didn't work.
Union gives me 2 line for each username, join makes me crazy, sub queries takes longtime and wrong results.
All help is appreciated.
Problem, solved with Kicstart's solution. Thank you very much for each help.
Can you provide the primary keys of the table? It would help us give better answers.
Also, you MUST include both conditions u.src=c.src AND u.id=c.id for join.
If the IDs of the two tables do not relate to each other, I suggest you use different attribute names.
Couple of sub queries?
SELECT a.src,
oBSum AS OutboundSUM,
oBCnt AS OutboundCNT,
iBSum AS InboundSUM,
iBCnt AS InboundCNT
FROM users u
LEFT OUTER JOIN (SELECT src, SUM(duration) AS oBSum, COUNT(*) AS oBCnt FROM call_history GROUP BY src) ob
ON u.src = ob.src
LEFT OUTER JOIN (SELECT dst, SUM(duration) AS iBSum, COUNT(*) AS iBCnt FROM call_history GROUP BY dst) ib
ON u.src = ib.dst
Related
I looked around for answers to this question but all the ones I tried simply didn't work. The other answer suggestions all threw errors for me. Maybe it's because I'm using using MariaDB ?.
SELECT * FROM 'view_winners'
I need top 3 in column 'class'
table view_winners is multiple left joins and I could not figure out how to limit 3 of the left join on table allClasses.
view_winners is:
`$view = "view_winners";
$db->query("DROP $view");
$db->query("CREATE VIEW $view AS
SELECT *
FROM thw22 evnt
LEFT JOIN allUsers usr
ON usr.user_id = evnt.e_owner_id
LEFT JOIN hw_vehicles veh
ON veh.vehicle_id = evnt.e_vehicle_id
LEFT JOIN hw_m_vehicle_class mcls
ON mcls.v_class_id = evnt.e_class_id
LEFT JOIN allClasses cls
ON mcls.cvm_id = cls.class_id
LEFT JOIN hw_v_scores sco
ON sco.v_score_id = evnt.e_score_id
WHERE (cls.class_name <> '' OR cls.class_name IS NOT NULL)
AND (sco.total <> '' OR sco.total IS NOT NULL)
ORDER BY cls.vehicle_type ASC, cls.class_name ASC, sco.total DESC
");`
It's probably best if I could LIMIT 3 on LEFT JOIN allClasses but I can't figure that out. So I figured I would loop through the result and unset rows over 3 in class in PHP. But again I could not figure out how to compare rows as looping through.
I need help with the LIMIT 3 on the JOIN or how to compare the results unsetting rows.
entry
class
score
786
sally
99
234
sally
90
456
bob
45
621
joe
90
964
joe
80
548
joe
66
346
joe
22
900
frank
89
700
frank
86
800
frank
72
123
frank
70
860
frank
50
333
frank
45
Desired results:
entry
class
score
786
sally
99
234
sally
90
456
bob
45
621
joe
90
964
joe
80
548
joe
66
900
frank
89
700
frank
86
800
frank
72
Might this answer help
And to clarify, it appears that for example, you want AT MOST, 3 entries per class (person name per sample data). If one class has only a single entry, get it. However, if someone else has 8 classes you want only the first 3 based on some pre-determined priority ordering, such as top 3 scores.
In your case, the OVER is partitioned by the "class", and the order by will be the score DESC (descending). So having the view give you this extra computed column (per class), you can then filter WHERE finalColumnNameYouAssign <= 3
I just answered similar question yesterday. See How to limit SQL query with JOIN
Here's my solution based on 2 linked tables, users and history for each user. There is also another solution there depending on your MySQL version.
SELECT *
FROM
`users` AS u
LEFT JOIN `history` AS h ON u.id = h.user_id
WHERE
FIND_IN_SET(h.id, (SELECT `list` FROM
(SELECT user_id, SUBSTRING_INDEX(GROUP_CONCAT(id SEPARATOR ','), ',', 3) AS `list` FROM
(SELECT h.user_id, h.id
FROM
`users` AS u
LEFT JOIN `history` AS h ON u.id = h.user_id
) AS `a`
GROUP BY user_id
) AS `b`
WHERE b.user_id = u.id
) )
Instead of having so many joins and confusing myself badly, I made a couple different views that I will need anyway for other statistics. Then by simply ordering by class ASC, score DESC I have a very simple master list of all classes in order then scores highest to lowest (along with all the other joined data). After that I can compare each row and limit 3 as follows:
SELECT * FROM
(SELECT *,
#rn := IF(#prev = class_name,
#rn + 1, 1)
AS rn,
#prev := class_name
FROM view_allScores
JOIN (SELECT #prev := NULL, #rn := 0)
AS vars
) AS T1
WHERE T1.rn <= 3
The confusing thing was that I was trying to add a LIMIT to a join and that kept confusing me.
I am using Php with join, I have two tables ("services" and "service_detail"), I want to get all services
but want to know which service selected or notselected by vendor
Here is my services table strcture
id service_name image
1 Abc abc.jpg
2 xyz xyz.jpg
3 OPS ops.jpg
4 tys tys.jpg
5 byp byp.jpg
Here is my services_detail table strcutre
id vendor_id service_id price
1 101 1 50
2 101 2 70
3 101 3 80
4 101 4 30
5 102 1 70
6 102 2 40
...
I tried with following query but showing only selected services, but i want to get all services with parameter ( selected or notselected)
Where i am wrong ? Here is my query
SELECT sd.vendor_id, sd.service_id, sd.price, s.service_name, s.image
FROM services_detail sd
LEFT JOIN services s
ON sd.service_id = s.id
WHERE sd.vendor_id = '101'
Move your where clause to be AND in ON clause:
AND sd.vendor_id = '101'
And interchange tables in join to get all servcies
SELECT sd.vendor_id, sd.service_id, sd.price, s.service_name, s.image,
IF (sd.vendor_id is not null, 'Opted', 'Not opted') as status
FROM services s
LEFT JOIN services_detail sd
ON sd.service_id = s.id AND sd.vendor_id = '101';
In simple words, when there is a where clause including filters on table of Left Join then it will act like INNER JOIN not LEFT JOIN.
I'm having a lot of trouble figuring out how to write this query. Here's an exmaple of the data set and what I need to query:
**System Table**
SystemID Active
1 T
2 T
3 T
4 F
5 F
6 F
**BlogPost Table**
BlogPostID SystemID Create_Month
100 2 Jan
101 2 Jan
102 2 Feb
103 3 Feb
104 3 Mar
105 6 Mar
106 6 Mar
**Comment Table**
Comment ID BlogPostID Liked
201 100 T
202 100 T
203 100 T
204 102 T
205 102 T
206 102 T
207 103 F
So, In words, I'm trying to get: By month, show me all the active systems who created a post during that month, the number of posts they made in aggregate, and the count of the subset of those posts who had a comment that was like.
The end result would be like:
Column 1 - Month
Column 2 - Count of Active Systems where a Post Created in Month
Column 3 - Count of Posts Applicable to those systems
Column 4 - Count of Applicable Posts that had comments that were liked
I don't even know where to start really. My terrible "this is obviously wrong" attempt is below. Any help is much appreciated, thanks!
SELECT
Month,
COUNT(DISTINCT system.systemid),
COUNT(blogpost.BlogPostID)
COUNT(comments.commentiD)
FROM
system INNER JOIN
blogpost ON system.systemid = blogpost.systemid INNER JOIN
comments ON blogpost.BlogPostID = comment.BlogPostID
WHERE
system.active = T
AND comments.like = T
GROUP BY month
A complicated one !
SELECT
b.Create_Month,
COUNT(DISTINCT s.SystemID) as SystemCount,
COUNT(DISTINCT b.BlogPostID) as PostsCount,
COUNT(DISTINCT t.BlogPostID) as PostsWithLike
FROM System s
JOIN BlogPost b
ON s.systemID = b.systemID
AND s.Active = 'T'
LEFT JOIN Comment c
ON b.BlogPostID = c.BlogPostID
LEFT JOIN
(
SELECT DISTINCT c.BlogPostID as BlogPostID
FROM
Comment c
GROUP BY c.BlogPostID
HAVING SUM(if(c.Liked='T',1,0))>0
) as t
ON b.BlogPostID = t.BlogPostID
GROUP BY b.Create_Month
This is probably what you want :
SELECT s.systemid, active, bp.create_month, bp.systemid, COUNT(bp.blogpostid), COUNT(c.liked)
FROM system AS s
LEFT OUTER JOIN Blogpost AS bp ON s.systemid = bp.systemid
LEFT OUTER JOIN Comment AS c ON bp.blogpostid = c.blogpostid
WHERE active = 'T' AND c.Liked = 'T' GROUP BY s.systemid,bp.create_month
Two tables
MEDIA_APPROVALS
[media_id] [firm_id] [approval_status]
FIRM_LIST
[firm_id] [firm_code]
End goal is to show what media is NOT approved by what firm.
By default, all media listed in the MEDIA_APPROVALS table is NOT approved by the firms listed in the FIRM_LIST table. So in order for media to be approved, the row must contain a firm_id with approval_status=1.
If a media piece is in the MEDIA_APPROVALS table & the row contains a firm_id and approval_status=0, that's easy - it's NOT approved.
Where it gets tricky to me is: if there is a MISSING ROW in the MEDIA_APPROVALS table for a media_id/firm_id connection, then that media_id is NOT approved for that firm.
Ultimately I want to arrive at this:
MEDIA_APPROVALS
100 1 1
100 2 1
101 1 0
101 2 0
101 3 1
102 1 1
FIRM_LIST
1 AA
2 BB
3 CC
QUERY OUTPUT
100 CC 0
101 AA 0
101 BB 0
102 BB 0
102 CC 0
I am a PHP/web programmer and NOT a db admin. The help is HUGELY appreciated!
So you need every possible combination of Media and Firm? Ooh, that's a CROSS JOIN. We don't get to do those very often:
WITH MediaFirms As (
SELECT m_id.media_id, f_id.firm_id
FROM (SELECT DISTINCT media_id FROM MEDIA_APPROVALS) m_id
CROSS JOIN (SELECT DISTINCT firm_ID FROM FIRM_LIST) f_id
)
SELECT mf.media_id, mf.firm_id, coalesce(ma.approval_status, 0) "approval_status"
FROM MediaFirms mf
LEFT JOIN MEDIA_APPROVALS ma ON ma.media_id = mf.media_id AND ma.firm_id = mf.firm_id
WHERE coalesce(ma.approval_status,0) <> 1;
I have a table by the following structure and records, All i want to do is to just extract orderid of those records whose status id is either 1 or 2 , i want to exclude all orderid with statusid=3 , , problem is that orderid 106 has both status 1 and 3 ...
I have written a sub-query which serves the purpose..
select *
from orders_status_history
where orders_id NOT IN
(select orders_id
from orders_status_history
where orders_status_id = 3)
is there any other way of doing this without using sub-queries as i have heard it hampers performance. As my query can return thousands of rows as well.
id order-id status-id
1 1 1
2 2 1
3 105 1
4 106 1
5 106 3
6 108 1
7 109 1
8 109 2
Any help or suggestion will be highly appreciated ..Thanks in advance..
You may do that:
SELECT osh.*
FROM orders_status_history osh
LEFT JOIN
orders_status_history oshd
ON oshd.orders_id = osh_orders_id
AND oshd.orders_status_id = 3
WHERE oshd.orders_id IS NULL
However, if you have an index on order_status_history (orders_id, orders_status_id), then the NOT IN query is just as fine.
You may want to read this:
NOT IN vs. NOT EXISTS vs. LEFT JOIN / IS NULL: MySQL
I wonder why you use sub query while you can use the following query
select orders_id from orders_status_history where orders_status_id <> 3
Please try this , and I hope it helps