Group by rows order by min price first - mysql

I have a table 'terms':
([id], [t_id], [d_start], [d_end], [price], [departure_from])
with values:
(12,10, 2018-5-5, 2018-5-15, 95, london),
(11,10, 2018-5-5, 2018-5-15, 60, london),
(10,10, 2018-5-5, 2018-5-15, 90, london),
( 9, 10, 2018-5-5, 2018-5-15, 90, prag),
( 8, 10, 2018-5-5, 2018-5-15, 85, prag),
( 7, 10, 2018-5-5, 2018-5-15, 70, prag),
( 6, 10, 2018-6-8, 2018-6-18, 30, london),
( 5, 10, 2018-6-8, 2018-6-18, 20, london),
( 4, 10, 2018-6-8, 2018-6-18, 90, london),
( 3, 10, 2018-6-8, 2018-6-18, 90, prag),
( 2, 10, 2018-6-8, 2018-6-18, 10, prag),
( 1, 10, 2018-6-8, 2018-6-18, 70, prag);
and I want to group by d_start,d_end,departure_from with order by price and I want to order by price first.
I have query:
(SELECT * FROM
(SELECT * FROM terms
WHERE t_id=10 ORDER BY price) t
GROUP BY d_start,d_end,departure_from ORDER BY d_start)
Result I want: 4 rows with min price :
(11,10, 2018-5-5, 2018-5-15, 60, london),
( 7, 10, 2018-5-5, 2018-5-15, 70, prag),
( 5, 10, 2018-6-8, 2018-6-18, 20, london),
( 2, 10, 2018-6-8, 2018-6-18, 10, prag),
My first question there. Thank you for any help.
I found result that work for me:
(SELECT * FROM
(SELECT * FROM terms
WHERE t_id=10 GROUP BY d_start,d_end,departure_from,price ORDER BY d_start) t
GROUP BY d_start,d_end,departure_from)
What do you think? It's OK?

With the information you gave, the main problem you have is the variable names. Just add an `` for every of them.
Like:
SELECT * FROM
(SELECT * FROM terms
WHERE t_id=10 ORDER BY price)
GROUP BY `start`,`end`,`from` ORDER BY start

You need to use correlated subquery for this...
select t.*
from terms t
where t.price = (
select min(t2.price)
from terms t2
where t2.d_start = t.d_start
and t2.d_end = t.d_end
and t2.departure_from = t.departure_from
)
order by t.d_start;

Related

GROUP_CONCAT not working in Sub-Query

I have tried this query to get the following data
SELECT
GROUP_CONCAT( sb.p_id ) ,
TRUNCATE( SUM( sb.total_amount ) , 2 ) grand_total,
TRUNCATE( SUM( sb.amount_wot ) , 2 ) sale_amount,
(SELECT TRUNCATE( SUM( (item_qty * item_price) * tax_price /100 ) , 2 )
FROM ci_bill_items
WHERE bill_id IN ( GROUP_CONCAT( sb.p_id ) ) ) tax_amount
FROM ci_suppliers_bills sb
WHERE sb.p_id >0
I got the expected result but not the tax_amount its return null but if i run the seperate query like :
SELECT TRUNCATE( SUM( (item_qty * item_price) * tax_price /100 ) , 2 )
FROM ci_bill_items
WHERE bill_id IN ( 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 71 )
Then i get the correct result. But all i want in one query like the first one, is group_concat not working like i tried bill_id IN ( GROUP_CONCAT( sb.p_id ) )? Help is much appriciated.
You can use FIND_IN_SET like this:
SELECT
GROUP_CONCAT( sb.p_id ) ,
TRUNCATE( SUM( sb.total_amount ) , 2 ) grand_total,
TRUNCATE( SUM( sb.amount_wot ) , 2 ) sale_amount,
(SELECT TRUNCATE( SUM( (item_qty * item_price) * tax_price /100 ) , 2 )
FROM ci_bill_items
WHERE FIND_IN_SET(bill_id, GROUP_CONCAT( sb.p_id ) ) > 0 ) tax_amount
FROM ci_suppliers_bills sb
WHERE sb.p_id >0
GROUP_CONCAT doesn't return a list, it returns a string. To get a list that you can use with IN, you need to run a subquery:
WHERE bill_id IN (SELECT p_id FROM ci_suppliers_bills
WHERE p_id > 0)

How to use MYSQL GROUP BY SUM with multiple columns

Basically the question is how to get the sum from #hours, groupping by #id, #code, #semester, #year columns from this
id, hours, code, semester, year
165, 6, 3, 1, 2012
166, 6, 16, 1, 2012
460, 8, 14, 2, 2012
461, 8, 16, 2, 2012
462, 15, 16, 2, 2013
463, 6, 1, 2, 2013
id, hours, code, semester, year, sum
165, 6, 3, 1, 2012, **6**
166, 6, 16, 1, 2012, **6**
460, 8, 14, 2, 2012, **8**
461, 8, 16, 2, 2012, **23**
462, 15, 16, 2, 2012, **23**
463, 6, 1, 2, 2013, **6**
I have tried a lot with GROUP BY, GROUP BY CONCAT, etc, but no success.
I want to group by all these columns in each row
Try this:
select id, code, semester, year, sum(hours) from `table` group by id,code,semester, year
to sum a values of a column you can use SUM() function of MYSQL and you can return it as on of fields like this for example the field of sum in this query would be total_hours
SELECT id,hours,code,semester,year, SUM(hours) AS total_hours
FROM table_name
GROUP BY id,code,semester, year

Return all rows from sub-query SQL?

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

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

find a duplicate series in SQL

I have a table with 3 columns containing a variable number of records based off of the first column which is a foreign key. I am trying to determine if I can detect when there is a duplicate across multiple rows for an entire series
declare #finddupseries table
(
portid int,
asset_id int,
allocation float
)
;
INSERT INTO #finddupseries
SELECT 250, 6, 0.05 UNION ALL
SELECT 250, 66, 0.8 UNION ALL
SELECT 250, 2, 0.105 UNION ALL
SELECT 250, 4, 0.0225 UNION ALL
SELECT 250, 5, 0.0225 UNION ALL
SELECT 251, 13, 0.6 UNION ALL
SELECT 251, 2, 0.3 UNION ALL
SELECT 251, 5, 0.1 UNION ALL
SELECT 252, 13, 0.8 UNION ALL
SELECT 252, 2, 0.15 UNION ALL
SELECT 252, 5, 0.05 UNION ALL
SELECT 253, 13, 0.4 UNION ALL
SELECT 253, 2, 0.45 UNION ALL
SELECT 253, 5, 0.15 UNION ALL
SELECT 254, 6, 0.05 UNION ALL
SELECT 254, 66, 0.8 UNION ALL
SELECT 254, 2, 0.105 UNION ALL
SELECT 254, 4, 0.0225 UNION ALL
SELECT 254, 5, 0.0225
select * from #finddupseries
The records for portid 250 and 254 match.
Is there any way I can write a query to detect this?
edit: yes, the entire series must match. Also, if there was a way to determine which one it DID match would be helpful as the actual table has around 10k records.
thanks!
This query will give you all the values converted into a string grouped by port_id
SELECT fus1.portid,
(
SELECT CONVERT (VARCHAR, fus2.asset_id) + CONVERT (VARCHAR, fus2.allocation) + ','
FROM #finddupseries fus2
WHERE 1=1
AND fus1.portid = fus2.portid
ORDER BY fus2.portid, fus2.asset_id, fus2.allocation
FOR XML PATH ('')
) AllValuesFromAllRows
FROM #finddupseries fus1
GROUP BY fus1.portid
the output should look like this
portid AllValuesFromAllRows
----------- ------------------------------------------------------
250 20.105,40.0225,50.0225,60.05,660.8,
251 20.3,50.1,130.6,
252 20.15,50.05,130.8,
253 20.45,50.15,130.4,
254 20.105,40.0225,50.0225,60.05,660.8,
Now, lets do a group by with a having!
;With DuplicateFinder as
(
SELECT fus1.portid,
(
SELECT CONVERT (VARCHAR, fus2.asset_id) + CONVERT (VARCHAR, fus2.allocation) + ','
FROM #finddupseries fus2
WHERE 1=1
AND fus1.portid = fus2.portid
ORDER BY fus2.portid, fus2.asset_id, fus2.allocation
FOR XML PATH ('')
) AllValuesFromAllRows
FROM #finddupseries fus1
GROUP BY fus1.portid
)
SELECT AllValuesFromAllRows, COUNT (*) NumDups
FROM DuplicateFinder
GROUP BY AllValuesFromAllRows
Having COUNT (*) > 1
You should get
AllValuesFromAllRows NumDups
----------------------------------------------- -----------
20.105,40.0225,50.0225,60.05,660.8, 2
So here is everything put together
SET NOCOUNT ON
declare #finddupseries table
(
portid int,
asset_id int,
allocation float
)
;
INSERT INTO #finddupseries
SELECT 250, 6, 0.05 UNION ALL
SELECT 250, 66, 0.8 UNION ALL
SELECT 250, 2, 0.105 UNION ALL
SELECT 250, 4, 0.0225 UNION ALL
SELECT 250, 5, 0.0225 UNION ALL
SELECT 251, 13, 0.6 UNION ALL
SELECT 251, 2, 0.3 UNION ALL
SELECT 251, 5, 0.1 UNION ALL
SELECT 252, 13, 0.8 UNION ALL
SELECT 252, 2, 0.15 UNION ALL
SELECT 252, 5, 0.05 UNION ALL
SELECT 253, 13, 0.4 UNION ALL
SELECT 253, 2, 0.45 UNION ALL
SELECT 253, 5, 0.15 UNION ALL
SELECT 254, 6, 0.05 UNION ALL
SELECT 254, 66, 0.8 UNION ALL
SELECT 254, 2, 0.105 UNION ALL
SELECT 254, 4, 0.0225 UNION ALL
SELECT 254, 5, 0.0225
;With PivotAssetIdAndAllocation as
(
SELECT fus1.portid,
(
SELECT CONVERT (VARCHAR, fus2.asset_id) + '_'+ CONVERT (VARCHAR, fus2.allocation) + '~~'
FROM #finddupseries fus2
WHERE 1=1
AND fus1.portid = fus2.portid
ORDER BY fus2.portid, fus2.asset_id, fus2.allocation
FOR XML PATH ('')
) AllValuesFromAllRows
FROM #finddupseries fus1
GROUP BY fus1.portid
)
,
ListOfDuplicates AS
(
SELECT AllValuesFromAllRows, COUNT (*) NumDups
FROM PivotAssetIdAndAllocation
GROUP BY AllValuesFromAllRows
Having COUNT (*) > 1
)
SELECT portid, AllValuesFromAllRows
FROM PivotAssetIdAndAllocation
WHERE AllValuesFromAllRows IN (SELECT AllValuesFromAllRows FROM ListOfDuplicates)
and the output is
portid AllValuesFromAllRows
----------- ----------------------------------------------------------------------
250 2_0.105~~4_0.0225~~5_0.0225~~6_0.05~~66_0.8~~
254 2_0.105~~4_0.0225~~5_0.0225~~6_0.05~~66_0.8~~
this should do the trick:
declare #finddupseries table
(
portid int,
asset_id int,
allocation float
)
;
INSERT INTO #finddupseries
SELECT 250, 6, 0.05 UNION ALL
SELECT 250, 66, 0.8 UNION ALL
SELECT 250, 2, 0.105 UNION ALL
SELECT 250, 4, 0.0225 UNION ALL
SELECT 250, 5, 0.0225 UNION ALL
SELECT 251, 13, 0.6 UNION ALL
SELECT 251, 2, 0.3 UNION ALL
SELECT 251, 5, 0.1 UNION ALL
SELECT 252, 13, 0.8 UNION ALL
SELECT 252, 2, 0.15 UNION ALL
SELECT 252, 5, 0.05 UNION ALL
SELECT 253, 13, 0.4 UNION ALL
SELECT 253, 2, 0.45 UNION ALL
SELECT 253, 5, 0.15 UNION ALL
SELECT 254, 6, 0.05 UNION ALL
SELECT 254, 66, 0.8 UNION ALL
SELECT 254, 2, 0.105 UNION ALL
SELECT 254, 4, 0.0225 UNION ALL
SELECT 254, 5, 0.0225 UNION ALL
SELECT 255, 13, 0.6 UNION ALL
SELECT 255, 2, 0.3 UNION ALL
SELECT 255, 5, 0.1
;with cteGetDupes
as
(
SELECT row_number() over (partition by asset_id, allocation
order by portid desc, asset_id desc, allocation desc)
AS RNDesc
, row_number() over (partition by asset_id, allocation
order by portid, asset_id, allocation)
AS RNAsc
, *
FROM #finddupseries
)
SELECT portid, asset_id, allocation
FROM cteGetDupes
WHERE RNDesc - RNAsc != 0
order by portid, asset_id, allocation