I need to find contiguous numbers ranges (min, max) from a set of "series" (only numbers).
I have written a SQL using #row_number but it works partially. If the row ID (int, primary, auto_increment) is not consecutive, it returns 2 result sets instead of just one.
Check this sqlfiddle to see how the query works.
So I need to find a way to do this not using #row_number or using it but with a condition to "bind" the 2 results into single one is the series are consecutive (even if the ID is not consecutive).
The correct result should be: (see this sqlfiddle)
MIN MAX PRODUCT_ID
220 230 20
1106 1108 18
1110 1110 18
1112 1120 18
Response time is also important.
Thanks
I assume that you're after something like this...
SELECT a.product_id
, a.series start
, MIN(c.series) end
FROM card a
LEFT
JOIN card b
ON b.product_id = a.product_id
AND b.series = a.series - 1
LEFT
JOIN card c
ON c.product_id = a.product_id
AND c.series >= a.series
LEFT
JOIN card d
ON d.product_id = a.product_id
AND d.series = c.series + 1
WHERE b.series IS NULL
AND c.series IS NOT NULL
AND d.series IS NULL
GROUP
BY a.product_id
, a.series;
http://sqlfiddle.com/#!2/32dc8/4
If performance remains an issue, then we can take another look at a solution with #variables
Related
The following SQL (PHP, MySQL) gives me rows with one id per row and the number of matches for each id, as the COUNT() for each.
SELECT ot.id, COUNT(ot.id)
FROM ot
JOIN tm on tm.mediaid = ot.id
WHERE tm.uploadedToS3 = 1
AND (
ot.something IN (1)
OR ot.somethingelse IN (1)
OR ot.anotherthing IN (1)
OR ot.morestuff IN (1)
OR ot.evenmorestuff IN (1)
)
GROUP BY ot.id
The result is something like...
ot.id COUNT(ot.id)
40153 4
40305 3
40309 35
40314 29
40315 12
40317 10
40318 16
40319 14
40324 154
40331 113
I would just like to know how many rows this query returns. I don't need any other information, just one integer. For the above, I am looking for the number of rows, i.e. I'd expect to just get the number 10.
How would I get this?
Thanks.
Use count(distinct) with no group by:
SELECT COUNT(DISTINCT ot.id)
FROM ot JOIN
tm
ON tm.mediaid = ot.id
WHERE tm.uploadedToS3 = 1 AND
(ot.something IN (1)
OR ot.somethingelseIN (1)
OR ot.anotherthing IN (1)
OR ot.morestuff IN (1)
OR ot.evenmorestuff IN (1)
)
I use a limit query to get a list of the top 5 directors counting also the total of their works e.g.
a 137
b 120
c 90
d 76
e 52
It really works but what about if with the last row there are also some names with equal works. And it usally happens...
f 52
g 52
h 52...
the query is:
SELECT
T_people.person,
COUNT(ID_films) AS CountOfID_films
FROM
((MT_films
JOIN ST_peoplefilms ON ((MT_films.ID_films = ST_peoplefilms.ID_films)))
JOIN T_people ON ((T_people.ID_person = ST_peoplefilms.ID_person)))
GROUP BY T_people.person, T_people.man
HAVING (T_people.man = 1)
ORDER BY COUNT(ST_peoplefilms.ID_films) DESC
LIMIT 5
thank's a lot
Create a subquery that gives the top 5 totals. Then use what you have now (you can remove LIMIT 5 and the ordering) and apply INNER JOIN on the subquery with respect to the totals. That will filter away all non-relevant rows.
How can I write this.. I have table 'Company' with a column 'Size'. The size references enums. I need to display the average company size as alias AS 'AverageEstimatedCompanySize' by substituting column 'Size' when column 'Size' is:
1 = 15
2 = 30
3 = 50
4 = 100
5 = 250
In other words, my table shows company size as either 1, 2, 3, 4 or 5. While 1 is actually a company size of 15.
This is all part of a bigger query:
SELECT COUNT(DISTINCT(ID)) AS 'Total # of Opps', AVG(Size*?) AS 'AverageEstimatedCompanySize'
FROM persontable AS POJT INNER JOIN opportunity
ON POJT.ID = opportunity.id
WHERE opportunity.TimeStamp >= '2012-01-01' AND opportunity.TimeStamp <= '2012-12-31' AND POJT.JobTitleID IN
(SELECT Id
FROM job
WHERE CategoryID IN
(SELECT id
FROM job_category
WHERE name IN ('Sc', 'Ma', 'Co', 'En', 'Tr')))
Sounds like something solvable with a case statement. The following is untested but should point you in the right direction.
SELECT
COUNT(DISTINCT(ID)) AS 'Total # of Opps',
AVG(
CASE Size
WHEN 1 THEN 15
WHEN 2 THEN 30
WHEN 3 THEN 50
WHEN 4 THEN 100
WHEN 5 THEN 250
END
) AS 'AverageEstimatedCompanySize'
FROM persontable AS POJT INNER JOIN opportunity
ON POJT.ID = opportunity.id
WHERE opportunity.TimeStamp >= '2012-01-01' AND opportunity.TimeStamp <= '2012-12-31' AND POJT.JobTitleID IN
(SELECT Id
FROM job
WHERE CategoryID IN
(SELECT id
FROM job_category
WHERE name IN ('Sc', 'Ma', 'Co', 'En', 'Tr')))
I'm thinking that one approach might be to modify the query to JOIN to the Company table appropriately (that's something you'll need to work out), and then modify the AVG statement:
... AVG(CASE `Size`
WHEN 1 THEN 15
WHEN 2 THEN 30
WHEN 3 THEN 50
WHEN 4 THEN 100
WHEN 5 THEN 250 END) AS 'AverageEstimatedCompanySize'
where Size is from the Company table.
Now, a more dynamic approach would be to create a new field, or even a new table, that maps those sizes and just JOIN the Company table and say the new table in the query and just grab the appropriate field per row then. That would get rid of the CASE statement.
I have a two tables first one is called teams and second one is called cpd and I want this result required (see result screen below). I tried myself but was not successful (see practice query below).
teams table
id name sub_cat_id
1 SACRAMENTO KINGS 19
2 KINGS 19
3 MIMAMI HEAT 19
4 HEAT 20
5 KITE 20
cpd table
id team_id status added_date
1 3 1 2012-05-26
2 3 1 2012-05-27
3 3 0 2012-05-28
practice Query
SELECT
t.`id`,t.`name`,IFNULL(cpd.status,0) AS resultStatus,IFNULL(cpd.added_date,CURDATE()) AS added_date
FROM `teams` t
LEFT JOIN cpd ON cpd.team_id = t.id
WHERE t.`sub_cat_id` = 19 OR cpd.added_date = CURDATE()
Result Screen (Required only those rows are black color in screen)
Update
Explanation ?
I am trying to get those rows who they are related with sub_cat_id = 19 like this in team table
Join team table with cpd table for cpd.status filed
cpd.status must be related with current date in cpd table like 2012-05-28
There are more than one way to get the desired result:
For example:
SELECT t.`id`,t.`name`,
IFNULL(cpd.status,0) AS resultStatus,
IFNULL(cpd.added_date,CURDATE()) AS added_date
FROM `teams` t
INNER JOIN cpd ON (cpd.team_id = t.id AND cpd.status = 0)
WHERE t.`sub_cat_id` = 19
OR
cpd.added_date = CURDATE()
Your JOIN ON cpd.team_id = t.idonly matches one tuple with the cpd table so for the other tuples date is set as NULL (because you are doing LEFT JOIN) and hence the where query gives only one tuple
SELECT
t.id,t.name,IFNULL(cpd.status,0) AS resultStatus,IFNULL(cpd.added_date,CURDATE()) AS added_date
FROM teams t
LEFT JOIN cpd ON cpd.team_id = t.id
WHERE t.sub_cat_id = 19 OR cpd.added_date = CURDATE()
GROUP BY t.id
I have the following query:
SELECT a.feeder_id, b.feeder_pr
FROM authors_article_feeders a
LEFT JOIN feeders b ON b.id = a.feeder_id
WHERE website_id =1
LIMIT 0 , 30
which results in:
feeder_id feeder_pr
18 2
18 2
18 2
18 2
32 6
What I need is to modify the above query so that it will manipulate this data so that the result would end up with a count of each feeder_pr, so in this case the result would be:
feeder_pr count
2 4
6 1
Any assistance is appreciated. If you have time please describe your solution so that I can learn from it while I'm at it.
Everything I've tried has ended in inaccurate results, usually with just one row instead of the expected 2.
You just need to add a GROUP BY And, you would not even need the joins
SELECT b.feeder_pr, COUNT(b.feeder_pr)
FROM feeders b
GROUP BY b.feeder_pr
SELECT b.feeder_pr, count(a.feeder_id) as count
FROM authors_article_feeders a
LEFT JOIN feeders b ON b.id = a.feeder_id
WHERE website_id =1
GROUP BY 1