I've got this query and I want to SUM all the results of the query grouped by the column omschrijving.
The query
SELECT b.BoekRegelBedrag as total, c.omschrijving, ctl.vd1, b.BoekRegelId
FROM condensations as c
LEFT JOIN condensations_to_ledgers as ctl
ON ctl.vd1 = c.code
LEFT JOIN BoekstukRegels as b
ON b.BoekRegelGrootboekNr = ctl.GrootboekNummer
LEFT JOIN GrootboekRekeningen as g
ON g.GrootboekNummer = ctl.GrootboekNummer
WHERE c.bedrijf_id = 118
AND b.BoekregelUserId = 118
AND ctl.bedrijf_id = 118
AND g.GrootboekUserId = 118
AND c.code < 10
AND g.BaSoort = 2
AND b.BoekRegelPeriode BETWEEN 201000 AND 201013
GROUP BY b.BoekRegelId
Is there a simple way to do this?
EDIT
I tried to SUM BoekRegelBedrag but then each record sums up a part in one way or the other and i got 4 results instead of one result with the total of the summed column
Since you've not clearly stipulated which column(s) should be summed, we have to guess. Assuming that the BoekRegelId column should not be summed (it seldom makes sense to do arithmetic on ID numbers) — and then not summing ctl.vd1 per comment — then:
SELECT omschrijving, SUM(total) AS sum_total
FROM (SELECT b.BoekRegelBedrag as total, c.omschrijving, ctl.vd1, b.BoekRegelId
FROM condensations AS c
LEFT JOIN condensations_to_ledgers AS ctl
ON ctl.vd1 = c.code
LEFT JOIN BoekstukRegels AS b
ON b.BoekRegelGrootboekNr = ctl.GrootboekNummer
LEFT JOIN GrootboekRekeningen AS g
ON g.GrootboekNummer = ctl.GrootboekNummer
WHERE c.bedrijf_id = 118
AND b.BoekregelUserId = 118
AND ctl.bedrijf_id = 118
AND g.GrootboekUserId = 118
AND c.code < 10
AND g.BaSoort = 2
AND b.BoekRegelPeriode BETWEEN 201000 AND 201013
GROUP BY b.BoekRegelId
) AS I
GROUP BY omschrijving;
Basically, I'm using your original query result as a 'table' in the FROM clause, and then aggregating on its columns in a way which might be what you're after.
An alternative, simpler approach may also be feasible if the core query is close to what you wanted:
SELECT c.omschrijving, SUM(b.BoekRegelBedrag) as total
FROM condensations AS c
LEFT JOIN condensations_to_ledgers AS ctl ON ctl.vd1 = c.code
LEFT JOIN BoekstukRegels AS b ON b.BoekRegelGrootboekNr = ctl.GrootboekNummer
LEFT JOIN GrootboekRekeningen AS g ON g.GrootboekNummer = ctl.GrootboekNummer
WHERE c.bedrijf_id = 118
AND b.BoekregelUserId = 118
AND ctl.bedrijf_id = 118
AND g.GrootboekUserId = 118
AND c.code < 10
AND g.BaSoort = 2
AND b.BoekRegelPeriode BETWEEN 201000 AND 201013
GROUP BY c.omschrijving;
Related
I have query with many joins and I'm searching for optimization for it.
It's about computers:
For examples I have:
Lenovo 8gbRAM 1TB core i5 ips etc. (all these after brand name are attributes)
I have configuration where, I want to change attribute 8gbRAM to 16gbRAM and I have to search for other item with all these attributes and 16gbRAM
Two tables:
**st_item**
- id
- name
...
**st_item_specification_attribute**
- id
- st_item_id
- attribute_id
- attribute_value_id
...
My problem is that my item has 15 attributes. When I tested with lower number of attributes I use this structure of query and it works, but now system has 85k items and over 1kk item attributes
This is the query:
SELECT `st_item`.id FROM `st_item`
LEFT JOIN `st_item_specification_attribute` `sisa_36590` ON st_item.id = sisa_36590.item_id AND sisa_36590.attribute_id = 365
LEFT JOIN `st_item_specification_attribute` `sisa_367910` ON st_item.id = sisa_367910.item_id AND sisa_367910.attribute_id = 367
LEFT JOIN `st_item_specification_attribute` `sisa_374641` ON st_item.id = sisa_374641.item_id AND sisa_374641.attribute_id = 374
LEFT JOIN `st_item_specification_attribute` `sisa_378366` ON st_item.id = sisa_378366.item_id AND sisa_378366.attribute_id = 378
LEFT JOIN `st_item_specification_attribute` `sisa_382500` ON st_item.id = sisa_382500.item_id AND sisa_382500.attribute_id = 382
LEFT JOIN `st_item_specification_attribute` `sisa_372134` ON st_item.id = sisa_372134.item_id AND sisa_372134.attribute_id = 372
LEFT JOIN `st_item_specification_attribute` `sisa_41268` ON st_item.id = sisa_41268.item_id AND sisa_41268.attribute_id = 412
LEFT JOIN `st_item_specification_attribute` `sisa_413368` ON st_item.id = sisa_413368.item_id AND sisa_413368.attribute_id = 413
LEFT JOIN `st_item_specification_attribute` `sisa_414929` ON st_item.id = sisa_414929.item_id AND sisa_414929.attribute_id = 414
LEFT JOIN `st_item_specification_attribute` `sisa_418496` ON st_item.id = sisa_418496.item_id AND sisa_418496.attribute_id = 418
LEFT JOIN `st_item_specification_attribute` `sisa_385748` ON st_item.id = sisa_385748.item_id AND sisa_385748.attribute_id = 385
LEFT JOIN `st_item_specification_attribute` `sisa_36625` ON st_item.id = sisa_36625.item_id AND sisa_36625.attribute_id = 366
LEFT JOIN `st_item_specification_attribute` `sisa_366355` ON st_item.id = sisa_366355.item_id AND sisa_366355.attribute_id = 366
LEFT JOIN `st_item_specification_attribute` `sisa_366816` ON st_item.id = sisa_366816.item_id AND sisa_366816.attribute_id = 366
LEFT JOIN `st_item_specification_attribute` `sisa_366370` ON st_item.id = sisa_366370.item_id AND sisa_366370.attribute_id = 366
WHERE (`parent_id`=1032) AND
(sisa_36590.attribute_value_id = 2230) AND
(sisa_367910.attribute_value_id = 2451) AND
(sisa_374641.attribute_value_id = 3793) AND
(sisa_378366.attribute_value_id = 2955) AND
(sisa_382500.attribute_value_id = 3879) AND
(sisa_372134.attribute_value_id = 2780) AND
(sisa_41268.attribute_value_id = 3363) AND
(sisa_413368.attribute_value_id = 3373) AND
(sisa_414929.attribute_value_id = 3378) AND
(sisa_418496.attribute_value_id = 3844) AND
(sisa_385748.attribute_value_id = 3036) AND
(sisa_36625.attribute_value_id = 2315) AND
(sisa_366355.attribute_value_id = 2408) AND
(sisa_366816.attribute_value_id = 2412) AND
(sisa_366370.attribute_value_id = 2420)
Query must compare specific pair attribute_id => attribute_value_id, that's the reason my "ON clause" to be with item_id and attribute_id and specific alias
You can use aggregation:
select i.id
from st_item i join
st_item_specification_attribute sisa
ON sisa.item_id = i.item_id
where i.parent_id = 1032 and
(sisa.attribute_id, attribute_value_id) in ( (365, 2230), (367, 2451), . . .)
group by i.id
having count(*) = 15;
You can move your WHERE conditions into ON conditions
and change LEFT JOIN to INNER JOIN.
SELECT `st_item`.id FROM `st_item`
JOIN `st_item_specification_attribute` `sisa_36590`
ON st_item.id = sisa_36590.item_id AND sisa_36590.attribute_id = 365
AND sisa_36590.attribute_value_id = 2230
JOIN `st_item_specification_attribute` `sisa_367910`
ON st_item.id = sisa_367910.item_id AND sisa_367910.attribute_id = 367
AND sisa_367910.attribute_value_id = 2451
...
WHERE `parent_id`=1032
2nd approach
SELECT `st_item`.id FROM `st_item`
JOIN `st_item_specification_attribute` `sisa`
ON st_item.id = sisa.item_id AND
(
(sisa.attribute_id = 365 AND sisa.attribute_value_id = 2230)
OR
(sisa.attribute_id = 367 AND sisa.attribute_value_id = 2451)
...
)
WHERE `parent_id`=1032
GROUP BY `st_item`.id
HAVING COUNT(*) = 15
I cannot predict the performance, but I think you could make on subselect out of all that joins
(I presume atribute_id and Attribute_value_id pairs are unique per item_id)
SELECT `st_item`.id FROM `st_item`
WHERE (`parent_id`=1032) AND
15 = (SELECT COUNT(*) FROM st_item_specification_attribute attr
WHERE `st_item`.id = attr.item_id
AND ( attribute_id = 365 AND attribute_value_id = 2230 OR
...
)
I would use a UNION ALL approach for this. It's easy to change, and fairly simple to read. Performance should be pretty good too:
--A CTE so you only have to change parent_id in one place
--I believe not all mysql versions support this, though
--You could of course just select the parent_id in de UNION ALL and
-- use a single WHERE in the outer query.
WITH st_item_id AS
(
SELECT id
, attribute_id
, attribute_value_id
FROM st_item
WHERE parent_id = 1032
)
SELECT UA.id
FROM (
SELECT st_item.id
FROM st_item_id
INNER JOIN st_item_specification_attribute sisa_36590
ON st_item_id.id = sisa_36590.item_id
AND sisa_36590.attribute_id = 365
AND sisa_36590.attribute_value_id = 2230
UNION ALL
SELECT st_item.id
FROM st_item_id
INNER JOIN st_item_specification_attribute sisa_367910
ON st_item_id.id = sisa_367910.item_id
AND sisa_367910.attribute_id = 367
AND sisa_367910.attribute_value_id = 2451
) UA
I am facing 1 issue with MySql query:
select sum(h.total_rooms) as total_rooms from reservation_details as rd LEFT JOIN hotels as h ON rd.hotel_id = h.id left join `chains` as `c` on `c`.`id` = `h`.`chain_id` where YEAR(rd.created_at) = 2016 and MONTH(rd.created_at) = 5 and rd.status >= 50 and h.chain_id = 2 GROUP BY rd.hotel_id
Above query returns :
total_rooms
48216
7700
13250
But
I need sum of the query.
Try to use sum() function like this and use ROLLUP with your query.
select sum(h.total_rooms) as total_rooms from reservation_details as rd
LEFT JOIN hotels as h ON rd.hotel_id = h.id
left join `chains` as `c` on `c`.`id` = `h`.`chain_id`
where YEAR(rd.created_at) = 2016 and MONTH(rd.created_at) = 5
and rd.status >= 50 and h.chain_id = 2 GROUP BY rd.hotel_id
WITH ROLLUP
I have a table tbl_loyaltypoints in this table a column status = 2 has default value
Now I have following Query to get all records
select lp.order_id, DATEDIFF(CURDATE(), FROM_UNIXTIME(lp.created_at)) as createon,
oi.deal_id, wo.returnWithin, lp.status
from tbl_loyaltypoints lp
inner join tbl_orders ord on lp.order_id = ord.id
inner join tbl_order_item oi on lp.order_id = oi.order_id
inner join tbl_workorders wo on oi.deal_id = wo.id
where ord.order_type = 1
order by lp.id DESC;
Output:
order_id createon deal_id returnWithin status
1045 4 160 20 2
1044 4 160 20 2
1043 20 160 20 2
I want to update status tbl_loyaltypoints.status when createon==returnWithin.
Is there any way to do this using Mysql?
You can transform the select into a join:
update tbl_loyaltypoints lp inner join
tbl_orders ord
on lp.order_id = ord.id inner join
tbl_order_item oi
on lp.order_id = oi.order_id inner join
tbl_workorders wo
on oi.deal_id = wo.id
set lp.status = ??
where ord.order_type = 1 and
DATEDIFF(CURDATE(), FROM_UNIXTIME(lp.created_at)) = wo.returnWithin;
You don't specify what the new status is. The ?? is a placeholder.
I need help about generating query for multiple column.
part of my tbl_advert_specific_fields_values table look like:
id advert_id field_name field_value
1 654 t1_sqft 50
2 655 t1_yearbuilt 1999
3 1521 t2_doorcount 5
4 656 t1_yearbuilt 2001
5 656 t1_sqft 29
6 654 t1_yearbuilt 2004
SELECT p.*, p.id AS id, p.title AS title, usr.id as advert_user_id,
p.street_num, p.street,c.icon AS cat_icon,c.title AS cat_title,c.title AS cat_title,
p.description as description,
countries.title as country_name,
states.title as state_name,
date_FORMAT(p.created, '%Y-%m-%d') as fcreated
FROM tbl AS p
LEFT JOIN tbl_advertmid AS pm ON pm.advert_id = p.id
INNER JOIN tbl_usermid AS am ON am.advert_id = p.id
LEFT JOIN tbl_users AS usr ON usr.id = am.user_id
INNER JOIN tbl_categories AS c ON c.id = pm.cat_id
INNER JOIN tbl_advert_specific_fields_values AS asfv ON asfv.advert_id = p.id
LEFT JOIN tbl_countries AS countries ON countries.id = p.country
LEFT JOIN tbl_states AS states ON states.id = p.locstate
WHERE p.published = 1 AND p.approved = 1 AND c.published = 1
AND (asfv.field_name = 't1_yearbuilt'
AND CONVERT(asfv.field_value,SIGNED) <= 2004 )
AND (asfv.field_name = 't1_sqft'
AND CONVERT(asfv.field_value,SIGNED) <= 50)
AND p.price <= 10174945 AND (p.advert_type_id = 1)
AND (c.id = 43 OR c.parent = 43)
GROUP BY p.id
ORDER BY p.price DESC
ok, the problem is in this asfv query part that are generated dynamically. It belong to objects which represent adverts by its specific fields. asfv is actually advert_specific_fields_values table (table name say all about it).
Without part:
AND (asfv.field_name = 't1_yearbuilt'
AND CONVERT(asfv.field_value,SIGNED) <= 2004 )
AND (asfv.field_name = 't1_sqft'
AND CONVERT(asfv.field_value,SIGNED) <= 50)
query return all adverts that belong on advert_type_id and price of them are less than 10.174.945,00 €.
All what I need is query update that return only adverts, for example t1_yearbuilt less than 2005 and t1_sqft less than 51 (advert_id => 654,656).
I also need query for values between for example t1_sqft >=30 AND t1_sqft <=50 (advert_id => 654).
Can anybody know how, update this query?
TNX
I have a query which uses a self join on 2 tables to return a single row of results. The problem I have is that if seat1 is empty, I don't get anything returned.
SELECT seat1.seat_type_id
, seat1.seat_type_qty
, seat2.seat_type_id
, seat2.seat_type_qty
FROM jos_sv_apptpro2_requests AS R
LEFT JOIN jos_sv_apptpro2_seat_counts AS seat1 ON R.id_requests = seat1.request_id
LEFT JOIN jos_sv_apptpro2_seat_counts AS seat2 ON R.id_requests = seat2.request_id
WHERE (seat1.seat_type_id = 6 AND seat2.seat_type_id = 7)
AND R.id_requests = 8703
AND R.resource = 3
This should return:
seat_type_id 6
seat_type_qty 0 <= this is the empty row
seat_type_id1 7
seat_type_qty 1
WHERE seat1.seat_type_id = 6 AND seat2.seat_type_id = 7
is what removes all rows with NULL values. You should move those condition to the JOIN criteria so that the RDBMS does what you are expecting:
LEFT JOIN jos_sv_apptpro2_seat_counts AS seat1 ON R.id_requests = seat1.request_id
AND seat1.seat_type_id = 6
LEFT JOIN jos_sv_apptpro2_seat_counts AS seat2 ON R.id_requests = seat2.request_id
AND seat2.seat_type_id = 7
Move your where clauses into the JOINs:
LEFT JOIN jos_sv_apptpro2_seat_counts AS seat1
ON (R.id_requests = seat1.request_id) AND (seat1.seat_type_id = 6)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
when you have them in the where clause, you're matching against the whole row. Doing it in the JOIN will do the filtering only on the particular records being joined.