Return all rows from sub-query SQL? - mysql

Now I wrote query SQL for getting rows limited by first query:
SELECT * FROM commenttoarticle a
WHERE a.idCommentToArticle = (SELECT CommentToArticlePID FROM commenttoarticle b)
ORDER BY a.idCommentToArticle DESC LIMIT 3
When I try to execute this query, I get:
#1242 - Subquery returns more than 1 row
How to resolve this issue? So, I need get all rows from sub-query.
If I want return one row - I need use GROUP BY, but it is not solution
Modified query:
SELECT a.idCommentToArticle FROM
commenttoarticle a WHERE a.CommentToArticlePID IN
(SELECT idCommentToArticle FROM commenttoarticle b) ORDER BY a.idCommentToArticle DESC LIMIT 3
Dump table commenttoarticle:
CREATE TABLE IF NOT EXISTS `commenttoarticle` (
`idCommentToArticle` int(11) NOT NULL AUTO_INCREMENT,
`CommentToArticleTime` int(11) NOT NULL,
`CommentToArticleIdArticle` int(11) NOT NULL,
`CommentToArticleComment` text NOT NULL,
`CommentToArticleIdUser` int(11) NOT NULL,
`CommentToArticlePID` int(11) NOT NULL,
PRIMARY KEY (`idCommentToArticle`),
UNIQUE KEY `idCommentToArticle_UNIQUE` (`idCommentToArticle`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=59 ;
--
-- Дамп данных таблицы `commenttoarticle`
--
INSERT INTO `commenttoarticle` (`idCommentToArticle`, `CommentToArticleTime`, `CommentToArticleIdArticle`, `CommentToArticleComment`, `CommentToArticleIdUser`, `CommentToArticlePID`) VALUES
(29, 0, 11, 'продажам?\nИнтересует не мега-звезда, а именно предметный, руками умеющий продавать сам и помогающий выстраивать это бизнесам.', 459, 0),
(30, 0, 11, '2', 459, 0),
(31, 0, 11, '3', 459, 0),
(36, 0, 11, '3.1', 459, 31),
(37, 1413822798, 11, 'also facing that prob. on the plteform of win 7', 459, 29),
(38, 0, 11, ' here i dont have internet connection.. #Samint Sinha thanks ill check it out maybe tomorrow.', 459, 29),
(39, 0, 11, ' Select max id and you will have dhe last row returned', 459, 29),
(32, 0, 11, '4', 459, 0),
(44, 1414354324, 11, 'How to do', 456, 29),
(45, 1414354469, 11, 'sfsfsf', 456, 29),
(46, 1414354708, 11, 'dddd', 456, 29),
(47, 1414357761, 11, 'sfsfs', 456, 0),
(57, 1414370833, 39, 'kkkppppppp', 456, 0),
(49, 1414358233, 11, 'VSF\nSFSF', 456, 0),
(50, 1414359589, 11, 'How to do', 456, 0),
(51, 1414359660, 11, 'sfsfsdf', 456, 0),
(52, 1414361057, 11, 'SDFSF', 456, 0),
(53, 1414364023, 11, 'dsfdsjfsifmsi', 456, 0),
(54, 1414364031, 11, 'sdfdskjfnskf', 456, 52),
(55, 1414364034, 11, 'sdfdskjfnskf', 456, 52),
(56, 1414364044, 11, 'fndsdfnsofosfi', 456, 52),
(58, 1414370841, 39, 'dfgdfgdgdgdgdgdfgdgdfg', 456, 0);
Result what I need:
Here is example at sqlfiddle: sqlfiddle.com/#!2/dbd82a/1 I need get last 3 rows with a unlimited COMMENTTOARTICLEPID for each first query, if exists. In example, I need get rows with IDCOMMENTTOARTICLE: 58, 57, 56, 52

SELECT a.*
FROM commenttoarticle a
JOIN commenttoarticle b
ON b.CommentToArticlePID = a.idCommentToArticle
ORDER
BY a.idCommentToArticle DESC
LIMIT 3

use IN instead of '=' before sub-select.

USe in instead of ==
SELECT * FROM commenttoarticle a WHERE a.idCommentToArticle in (SELECT CommentToArticlePID FROM commenttoarticle b) ORDER BY a.idCommentToArticle DESC LIMIT 3

Use IN instead of = because your query returns lot of values:
SELECT * FROM commenttoarticle a
WHERE a.idCommentToArticle IN (
SELECT CommentToArticlePID
FROM commenttoarticle b)
ORDER BY a.idCommentToArticle DESC LIMIT 3

You can use limit in both sub query or main query or both.
If you need only 3 result then add limit at main query
SELECT * FROM commenttoarticle a WHERE a.idCommentToArticle IN (SELECT CommentToArticlePID FROM commenttoarticle b) ORDER BY a.idCommentToArticle DESC LIMIT 3
If you want 3 result at sub query then it will be like this
SELECT * FROM commenttoarticle a WHERE a.idCommentToArticle IN (SELECT CommentToArticlePID FROM commenttoarticle b LIMIT 3) ORDER BY a.idCommentToArticle DESC
If you want both
SELECT * FROM commenttoarticle a WHERE a.idCommentToArticle IN (SELECT CommentToArticlePID FROM commenttoarticle b LIMIT 3) ORDER BY a.idCommentToArticle DESC LIMIT 3

I am thinking that your subquery returns more than 1 row hence replace your "=" with "IN". Like this...
SELECT * FROM commenttoarticle a
WHERE a.idCommentToArticle IN (SELECT CommentToArticlePID FROM commenttoarticle b)
ORDER BY a.idCommentToArticle DESC LIMIT 3

Related

Get previous X days of revenue for each group

Here is my table
CREATE TABLE financials (
id INT(6) UNSIGNED AUTO_INCREMENT PRIMARY KEY,
CountryID VARCHAR(30) NOT NULL,
ProductID VARCHAR(30) NOT NULL,
Revenue INT NOT NULL,
cost INT NOT NULL,
reg_date TIMESTAMP
);
INSERT INTO `financials` (`id`, `CountryID`, `ProductID`, `Revenue`, `cost`, `reg_date`) VALUES
( 1, 'Canada', 'Doe' , 20, 5, '2010-01-31 12:01:01'),
( 2, 'USA' , 'Tyson' , 40, 15, '2010-02-14 12:01:01'),
( 3, 'France', 'Keaton', 80, 25, '2010-03-25 12:01:01'),
( 4, 'France', 'Keaton',180, 45, '2010-04-24 12:01:01'),
( 5, 'France', 'Keaton', 30, 6, '2010-04-25 12:01:01'),
( 6, 'France', 'Emma' , 15, 2, '2010-01-24 12:01:01'),
( 7, 'France', 'Emma' , 60, 36, '2010-01-25 12:01:01'),
( 8, 'France', 'Lammy' ,130, 26, '2010-04-25 12:01:01'),
( 9, 'France', 'Louis' ,350, 12, '2010-04-25 12:01:01'),
(10, 'France', 'Dennis',100,200, '2010-04-25 12:01:01'),
(11, 'USA' , 'Zooey' , 70, 16, '2010-04-25 12:01:01'),
(12, 'France', 'Alex' , 2, 16, '2010-04-25 12:01:01');
For each product and date combination, I need to get the revenue for previous 5 days. For instance, for Product ‘Keaton’, the last purchase was on 2010-04-25, it will only sum up revenue between 2010-04-20 to 2010-04-25 and therefore it will be 210. While for "Emma", it would return 75, since it would sum everything between 2010-01-20 to 2010-01-25.
SELECT ProductID, sum(revenue), reg_date
FROM financials f
Where reg_date in (
SELECT reg_date
FROM financials as t2
WHERE t2.ProductID = f.productID
ORDER BY reg_date
LIMIT 5)
Unfortunately, when i use either https://sqltest.net/ or http://sqlfiddle.com/ it says that 'LIMIT & IN/ALL/ANY/SOME subquery' is not supported. Would my query work or not?
Your query is on the right track, but probably won't work in MySQL. MySQL has limitations on the use of in and limit with subqueries.
Instead:
SELECT f.ProductID, SUM(f.revenue)
FROM financials f JOIN
(SELECT ProductId, MAX(reg_date) as max_reg_date
FROM financials
GROUP BY ProductId
) ff
ON f.ProductId = ff.ProductId and
f.reg_date >= ff.max_reg_date - interval 5 day
GROUP BY f.ProductId;
EDIT:
If you want this for each product and date combination, then you can use a self join or correlated subquery:
SELECT f.*,
(SELECT SUM(f2.revenue)
FROM financials f2
WHERE f2.ProductId = f.ProductId AND
f2.reg_date <= f.reg_date AND
f2.reg_date >= f.reg_date - interval 5 day
) as sum_five_preceding_days
FROM financials f;
After some trials I ended up with some complex query, that I think it solves your problem
SELECT
financials.ProductID, sum(financials.Revenue) as Revenues
FROM
financials
INNER JOIN (
SELECT ProductId, GROUP_CONCAT(id ORDER BY reg_date DESC) groupedIds
FROM financials
group by ProductId
) group_max
ON financials.ProductId = group_max.ProductId
AND FIND_IN_SET(financials.id, groupedIds) BETWEEN 1 AND 5
group by financials.ProductID
First I used group by financials.ProductID to count revenues by products. The real problem you are facing is eliminating all rows that are not in the top 5, for each group. For that I used the solution from this question, GROUP_CONCAT and FIND_IN_SET, to get the top 5 result without LIMIT. Instead of WHERE IN I used JOIN but with this, WHERE IN might also work.
Heres the FIDDLE

Why operator LIMIT does not work correctly?

I wrote the next query SQL for getting last comments with re-comments:
SELECT c.*, ar.ArticleName, ar.idArticle, du.DetailToUsersName, du.DetailToUsersPhoto, COUNT(c.idCommentToArticle) AS CNT, CASE WHEN d.Count IS NULL THEN 0 ELSE d.Count END AS CountLikes
FROM commenttoarticle c
INNER JOIN (SELECT CommentToArticlePID FROM commenttoarticle
GROUP BY CommentToArticlePID
ORDER BY CommentToArticlePID LIMIT 3) AS articleComments
USING (CommentToArticlePID)
LEFT JOIN article ar ON c.CommentToArticleIdArticle = ar.idArticle
LEFT JOIN detailtousers du ON du.idDetailToUsers = c.CommentToArticleIdUser
LEFT JOIN `likes` d ON (d.IdNote = c.idCommentToArticle AND d.LikeType = 6)
WHERE c.CommentToArticleIdArticle = 11
GROUP BY c.idCommentToArticle
So, why operator LIMIT 3 in sub-query select does not work? Now this query shows all rows from table commenttoarticle
I seem that need do somethink like as:
SELECT...
FROM (select * from commenttoarticle commenttoarticle c INNER JOIN
(SELECT distinct(CommentToArticlePID)
FROM commenttoarticle b
ORDER BY CommentToArticlePID
LIMIT 2) AS commenttoarticle USING (CommentToArticlePID)) as c
LEFT JOIN article ar ON c.CommentToArticleIdArticle = ar.idArticle...
Dump table commenttoarticle:
CREATE TABLE IF NOT EXISTS `commenttoarticle` (
`idCommentToArticle` int(11) NOT NULL AUTO_INCREMENT,
`CommentToArticleTime` int(11) NOT NULL,
`CommentToArticleIdArticle` int(11) NOT NULL,
`CommentToArticleComment` text NOT NULL,
`CommentToArticleIdUser` int(11) NOT NULL,
`CommentToArticlePID` int(11) NOT NULL,
PRIMARY KEY (`idCommentToArticle`),
UNIQUE KEY `idCommentToArticle_UNIQUE` (`idCommentToArticle`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=59 ;
INSERT INTO `commenttoarticle` (`idCommentToArticle`, `CommentToArticleTime`, `CommentToArticleIdArticle`, `CommentToArticleComment`, `CommentToArticleIdUser`, `CommentToArticlePID`) VALUES
(29, 0, 11, 'продажам?\nИнтересует не мега-звезда, а именно предметный, руками умеющий продавать сам и помогающий выстраивать это бизнесам.', 459, 0),
(30, 0, 11, '2', 459, 0),
(31, 0, 11, '3', 459, 0),
(36, 0, 11, '3.1', 459, 31),
(37, 1413822798, 11, 'also facing that prob. on the plteform of win 7', 459, 29),
(38, 0, 11, ' here i dont have internet connection.. #Samint Sinha thanks ill check it out maybe tomorrow.', 459, 29),
(39, 0, 11, ' Select max id and you will have dhe last row returned', 459, 29),
(32, 0, 11, '4', 459, 0),
(44, 1414354324, 11, 'How to do', 456, 29),
(45, 1414354469, 11, 'sfsfsf', 456, 29),
(46, 1414354708, 11, 'dddd', 456, 29),
(47, 1414357761, 11, 'sfsfs', 456, 0),
(57, 1414370833, 39, 'kkkppppppp', 456, 0),
(49, 1414358233, 11, 'VSF\nSFSF', 456, 0),
(50, 1414359589, 11, 'How to do', 456, 0),
(51, 1414359660, 11, 'sfsfsdf', 456, 0),
(52, 1414361057, 11, 'SDFSF', 456, 0),
(53, 1414364023, 11, 'dsfdsjfsifmsi', 456, 0),
(54, 1414364031, 11, 'sdfdskjfnskf', 456, 52),
(55, 1414364034, 11, 'sdfdskjfnskf', 456, 52),
(56, 1414364044, 11, 'fndsdfnsofosfi', 456, 52),
(58, 1414370841, 39, 'dfgdfgdgdgdgdgdfgdgdfg', 456, 0);
Dump table article:
CREATE TABLE IF NOT EXISTS `article` (
`idArticle` int(11) NOT NULL AUTO_INCREMENT,
`ArticleName` varchar(255) NOT NULL,
`ArticleTime` int(11) NOT NULL,
`ArticleDescription` varchar(500) NOT NULL,
`ArticleText` text NOT NULL,
`ArticleToUserID` int(11) DEFAULT NULL,
`ArticleCategory` int(11) NOT NULL,
`ArticleView` int(11) NOT NULL,
`ArticleCountry` int(11) NOT NULL,
`ArticlePhoto` varchar(150) NOT NULL,
`ArticleCity` int(11) NOT NULL,
PRIMARY KEY (`idArticle`),
UNIQUE KEY `idArticle_UNIQUE` (`idArticle`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=50 ;
By constructing a self join on comments yuo're not limiting but multiply the result.
What you need is a single subquery on comments table
SELECT c.*, ar.ArticleName,
ar.idArticle, du.DetailToUsersName,
du.DetailToUsersPhoto, COALECSE(SUM(d.count), 0)
FROM
(SELECT *
FROM
commenttoarticle
WHERE
CommentToArticleIdArticle = 11
ORDER BY
CommentToArticlePID, idCommentToArticle DESC
LIMIT 3
) c
LEFT JOIN
article ar
ON c.CommentToArticleIdArticle = ar.idArticle
LEFT JOIN
detailtousers du
ON du.idDetailToUsers = c.CommentToArticleIdUser
LEFT JOIN
likes d
ON (d.IdNote = c.idCommentToArticle AND d.LikeType = 6)
GROUP BY
c.idCommentToArticle
I have made the assumption that a comment can have multiple entries in the likes table, otherwise the subquery and the group by is not necesarry.
The USING(column_list) clause names a list of columns that must exist in both tables.
reference: http://dev.mysql.com/doc/refman/5.0/en/join.html
CommentToArticlePID is not in your first table.
Also, what is the point of joining a single column? Yes, if you want to limit, this might be applicable, but then why us LIMIT?

MySQL with Where IN and Distinct and Limit

SELECT id, server_id, start_time, end_time
FROM errors
WHERE server_id in (3, 12, 24, 25, 26, 27, 28, 29, 30)
ORDER BY id DESC
LIMIT 9
This is the query I'm trying to run to give me results where the server_id = 3, 12, 24, 25, 26, 27, 28, 29, 30. Instead, what I receive is server_id = 25, 25, 12, 25, 27, 27, 28, 28, 27. Note the repeating server_ids. The query gives me unique id but duplicate server_id.
Is there a way I can get results that would show me the last id for each server_id?
I've tried doing ORDER BY server_id but that gives me the same issue.
I tried running DISTINCT but that also does not work.
you'll have to use some aggregation functions.
Something like
select
server_id,
max(id),
avg(start_time),--for example
avg(end_time)--for example
from errors
where server_id in (3, 12, 24, 25, 26, 27, 28, 29, 30)
group by server_id
order by id desc
if you need tht start_time and end_time corresponding to the max id by server_id, you may do
select e.id, e.server_id, e.start_time, e.end_time
from errors e
join (select server_id, max(id) maxid
from errors
group by server_id) t
on t.maxid = e.id and e.server_id = t.server_id
where e.server_id in (3, 12, 24, 25, 26, 27, 28, 29, 30)
order by e.id DESC
The issue you have is that you need only one record from each server with the max ID.. and relative information. You need to limit the results to just that max ID... Here's one way...
SELECT id, server_id, start_time, end_time
FROM errors
WHERE server_id in (3, 12, 24, 25, 26, 27, 28, 29, 30)
and ID = (Select max(ID) from errors E2 where E2.server_ID=errors.server_ID)
ORDER BY id DESC
LIMIT 9

Mysql Match and count in the same table

I'm having an trouble with count product with some conditions on the same table..
Table structure:
INSERT INTO `filter` (`filter_seq_id`, `group_id`, `product_seq_id`) VALUES
(1, 1, 10),
(2, 1, 11),
(3, 1, 12),
(4, 1, 13),
(5, 2, 14),
(6, 2, 15),
(7, 2, 16),
(8, 2, 17),
(9, 3, 18),
(10, 3, 19),
(11, 3, 20),
(12, 3, 21),
(13, 4, 20),
(14, 4, 11),
(15, 4, 27),
(16, 4, 29),
(17, 5, 11),
(18, 5, 20),
(19, 5, 27),
(20, 5, 13);
Here i want count distinct product_seq_id for the group_id (1,2,3) only if product_seq_id also exits in both (4,5) group id..
for example:
group_id -> 1 found product_seq_id 11 in 4,5 so distinct count is 1
group_id -> 2 found nothing
group_id -> 3 found product_seq_id 20 in 4,5 so distinct count is 1
i have tried below query its not returning has i expect
its counting if product_seq_id exists in any one of (4,5)
And i want to count only if product_seq_id exits on both "4" and "5" group_id
SELECT
`f`.`group_id`, count(distinct f.product_seq_id) as count
FROM
filter f
JOIN
filter ff ON `ff`.`product_seq_id` = `f`.`product_seq_id`
AND `f`.`group_id` IN (1,2,3)
AND `ff`.`group_id` IN (4,5)
GROUP BY `f`.`group_id`
http://sqlfiddle.com/#!2/996c1/1
Is this what you are looking for?
select f123.GROUP_ID, count(f123.PRODUCT_SEQ_ID)
from (select product_seq_id from filter where group_id=4) f4
inner join (select product_seq_id from filter where group_id=5) f5
on f4.product_seq_id = f5.product_seq_id
inner join (select group_id, product_seq_id from filter where group_id<4) f123
on f123.product_seq_id = f5.product_seq_id
group by GROUP_ID order by GROUP_ID
The first two subselects selects all of the product_seq_id which are in filter in the group 4 or 5. Those 2 list are joined together only if both contain the same product_seq_id.
The Result of this is all the product_seq_id which are both in group 4 and group 5 (in this example 11 and 20)
Next this result is joined with the last subselect, which selects all group_id and product_seq_id in the groups 1 to 3. They are only joined if they contain any product_seq_id, which is in the previous result of the other join (so if they contain the product_seq_id 11 or 20). The Result of this looks like this:
Group_ID, Product_Seq_ID
1 11
3 20
This result is then grouped by the Group_ID and the amount of product_seq_id in each group is counted
EDIT: Added Explanation

MySQL include zero rows when using COUNT with LEFT OUTER JOIN and GROUP BY

How can I avoid eliminating the users with zero meetings? I'm aware there are similar questions, but this code is quite a bit more complex.
SELECT user.userID, user.contactName, user.email, COUNT( * ) AS meetingsCount
FROM user
LEFT OUTER JOIN meeting ON user.userID = meeting.userID
WHERE user.userID NOT
IN ( 1, 2, 3, 4, 5, 59, 62, 63, 64, 66, 69, 71, 72, 73, 78, 107 )
AND SUBSTRING( meeting.meetingCode, 5, 2 )
BETWEEN 12
AND 22
AND SUBSTRING( meeting.meetingCode, 7, 2 )
BETWEEN 01
AND 12
AND SUBSTRING( meeting.meetingCode, 9, 2 )
BETWEEN 01
AND 31
GROUP BY user.userID, contactName, email
ORDER BY meetingsCount DESC
You need to put the logic for the meeting code table in your join. Otherwise users matching the records you are filtering out from the meeting table will be filtered out of your results. Making your JOIN essentially an INNER join. I think you also should put single quotes around the values in your BETWEEN clauses.
SELECT user.userID, user.contactName, user.email, COUNT( meeting.userID ) AS meetingsCount
FROM user
LEFT OUTER JOIN meeting ON user.userID = meeting.userID
AND SUBSTRING( meeting.meetingCode, 5, 2 ) BETWEEN '12' AND '22'
AND SUBSTRING( meeting.meetingCode, 7, 2 ) BETWEEN '01' AND '12'
AND SUBSTRING( meeting.meetingCode, 9, 2 ) BETWEEN '01' AND '31'
WHERE user.userID NOT IN ( 1, 2, 3, 4, 5, 59, 62, 63, 64, 66, 69, 71, 72, 73, 78, 107 )
GROUP BY user.userID, contactName, email
ORDER BY meetingsCount DESC