I am trying to get the total amount spent on transactions with a specific product sold during the period below.
SELECT
i.Customer,
SUM(i.GrandTotal)
FROM
transaction i
WHERE EXISTS
(SELECT
1
FROM
transactionline il
INNER JOIN product p
ON p.ProductId = il.ProductId
WHERE i.InvoiceDate >= '2016-09-01 00:00:00'
AND i.InvoiceDate <= '2017-08-31 23:59:59'
AND p.TableProductType = 25)
GROUP BY i.Customer;
My problem is that this query has a result the total amount spent during that period and not only transactions with that product involved
I started of with something like this :
SELECT
i.Customer,
SUM(i.GrandTotal)
FROM
transaction i,transactionline il , product p
WHERE i.InvoiceDate >= '2016-09-01 00:00:00'
AND i.InvoiceDate <= '2017-08-31 23:59:59'
AND p.TableProductType = 25);
But this also took much longer and the final result was wrong (cause of the multiplication caused by the join between transaction and transaction line)
few ways, all solutions using the with following as its data source directly before query, but substitute with your table name
with dat
as
(
select 1 tranid,'N' Tableproducttype,9.00 GrandTotal union all
select 1,'N',11.12 union all
select 1,'N',14.23 union all
select 1,'25',8.88 union all
select 1,'N',7.77 union all
select 1,'Y',6.66 union all
select 2,'N',3.21 union all
select 2,'N',19.13 union all
select 2,'Y',1.23 union all
select 3,'Y',4.31 union all
select 4,'Y',15.43 union all
select 4,'Y',15.12 union all
select 5,'N',14.32)
1.) works using an IN
select tranid,sum(GrandTotal) GrandTotal
from dat
where tranid in (select tranid from dat where TableProductType = '25')
group by tranid
2.) using an exists
select tranid,sum(GrandTotal) GrandTotal
from dat
where exists (select 'x' from dat dat_inner
where dat_inner.TableProductType = '25'
and dat_inner.tranid = dat.tranid)
group by tranid
3.) using having, but could be slow
select tranid,sum(GrandTotal) GrandTotal
from dat
group by tranid
having sum(case when TableProductType = '25' then 1 else 0 end)>0 /* at least one product of type 25 */
Related
I want to create a stats page for my website. However I have the problem that if I run my query it will not be merged if the sting is the same. Any idea how to fix this?
My query:
SELECT * FROM (
SELECT dj_1, count(*) AS uren
FROM dj_rooster
WHERE week = '28' GROUP BY id_1
ORDER BY count(*) DESC
) x
UNION ALL
SELECT * FROM (
SELECT dj_1, count(*) AS uren
FROM djpaneel_shows_uren
WHERE week = '28' AND active = '1'
GROUP BY dj_1
ORDER BY count(*) DESC
) x
My results:
Jack - 7
Jeremy - 5
Jack - 1
Thanks in advance for your help
There is no need to aggregate twice or more.
Use UNION ALL to get all the rows from the 2 tables and then aggregate:
SELECT t.dj_1, COUNT(*) AS uren
FROM (
SELECT dj_1 FROM dj_rooster
WHERE week = '28'
UNION ALL
SELECT dj_1 FROM djpaneel_shows_uren
WHERE week = '28' AND active = '1'
) t
GROUP BY t.dj_1
ORDER BY uren DESC
I need to create a MYSQL query that will return the following:
excel
this is my query
SELECT t1.fecha_salida,
t1.agencia,
t2.fecha_salida,
t2.directa
FROM (SELECT fecha_salida, COUNT(*) AS agencia
FROM ventas
WHERE ventas.eliminado = 0 AND ventas.cliente_id !=2
GROUP BY fecha_salida) AS t1,
(SELECT fecha_salida, COUNT(*) AS directa
FROM ventas
WHERE ventas.eliminado = 0 AND ventas.cliente_id =2
GROUP BY fecha_salida) AS t2
GROUP BY t1.fecha_salida
my table is:
|------ |Columna|Tipo|Nulo|Predeterminado |------
|//**venta_id**//|int(11)|No| |usuario_id|int(11)|No|
|tour_id|int(11)|No| |cliente_id|int(11)|No| |vehiculo_id|int(11)|No|
|cashflow_id|int(11)|No| |total_compra|int(6)|No|
|total_pagado|int(6)|No| |total_iva|int(6)|No|
|total_comision|int(11)|No| |a_pagar|int(11)|No|
|fecha_venta|datetime|No| |fecha_salida|date|No|
|concretada|tinyint(1)|No| |pasajeros|int(3)|No|
|nombre|varchar(500)|Sí|NULL |direccion|varchar(500)|Sí|NULL
|observaciones|varchar(500)|Sí|NULL |forma_pago|tinyint(2)|No|
|eliminado|tinyint(1)|No|
Can you help me
You can use UNION to combine two queries that have same structure , also you should select from combined result and then order them
SELECT * FROM (
SELECT fecha_salida, COUNT(*) AS agencia
FROM ventas
WHERE `fecha_venta` between '2012-03-11 00:00:00' and '2019-08-30 23:59:00'
and ventas.eliminado = 0
AND ventas.cliente_id = 2
GROUP BY fecha_salida
UNION
SELECT fecha_salida, COUNT(*) AS agencia
FROM ventas
WHERE `fecha_venta` between '2012-03-11 00:00:00' and '2019-08-30 23:59:00'
and ventas.eliminado = 0
AND ventas.cliente_id != 2
GROUP BY fecha_salida
) RESULT
ORDER BY agencia
I have two SELECT statements that give the values "TotalSales" and "VendorPay_Com". I want to be able to subtract VendorPay_Com from TotalSales within the one MySQL statement to get the value "Outstanding_Funds" but I haven't found a reliable way to do so.
These are my two statements:
Query 1:
SELECT SUM(Price) AS TotalSales
FROM PROPERTY
WHERE Status = 'Sold';
Query 2:
SELECT SUM(AC.Amount) AS VendorPay_Comm
FROM (
SELECT Amount FROM lawyer_pays_vendor
UNION ALL
SELECT CommissionEarned AS `Amount` FROM COMMISSION AS C WHERE C.`status` = 'Paid') AS AC
Any help on this matter would be greatly appreciated :)
You can do it as follows :
select (select ...) - (select ...)
In your example, simply :
select
(
SELECT SUM(Price) AS TotalSales
FROM PROPERTY
WHERE Status = 'Sold'
)
-
(
SELECT SUM(AC.Amount) AS VendorPay_Comm
FROM (
SELECT Amount FROM lawyer_pays_vendor
UNION ALL
SELECT CommissionEarned AS `Amount` FROM COMMISSION AS C WHERE C.`status` = 'Paid') AS AC
) AS Outstanding_Funds
Try
SELECT TotalSales-VendorPay_Comm AS Outstanding_Funds
FROM
(SELECT SUM(Price) AS TotalSales
FROM PROPERTY
WHERE Status = 'Sold') t1,
(SELECT SUM(Amount) AS VendorPay_Comm
FROM (SELECT Amount FROM lawyer_pays_vendor
UNION ALL
SELECT CommissionEarned AS Amount
FROM COMMISSION
WHERE Status = 'Paid') t0) t2
Here is sqlfiddle
I have a table called receiving with 4 columns:
id, date, volume, volume_units
The volume units are always stored as a value of either "Lbs" or "Gals".
I am trying to write an SQL query to get the sum of the volumes in Lbs and Gals for a specific date range. Something along the lines of: (which doesn't work)
SELECT sum(p1.volume) as lbs,
p1.volume_units,
sum(p2.volume) as gals,
p2.volume_units
FROM receiving as p1, receiving as p2
where p1.volume_units = 'Lbs'
and p2.volume_units = 'Gals'
and p1.date between "2012-01-01" and "2012-03-07"
and p2.date between "2012-01-01" and "2012-03-07"
When I run these queries separately the results are way off. I know the join is wrong here, but I don't know what I am doing wrong to fix it.
SELECT SUM(volume) AS total_sum,
volume_units
FROM receiving
WHERE `date` BETWEEN '2012-01-01'
AND '2012-03-07'
GROUP BY volume_units
You can achieve this in one query by using IF(condition,then,else) within the SUM:
SELECT SUM(IF(volume_units="Lbs",volume,0)) as lbs,
SUM(IF(volume_units="Gals",volume,0)) as gals,
FROM receiving
WHERE `date` between "2012-01-01" and "2012-03-07"
This only adds volume if it is of the right unit.
This query will display the totals for each ID.
SELECT s.`id`,
CONCAT(s.TotalLbsVolume, ' ', 'lbs') as TotalLBS,
CONCAT(s.TotalGalVolume, ' ', 'gals') as TotalGAL
FROM
(
SELECT `id`, SUM(`volume`) as TotalLbsVolume
FROM Receiving a INNER JOIN
(
SELECT `id`, SUM(`volume`) as TotalGalVolume
FROM Receiving
WHERE (volume_units = 'Gals') AND
(`date` between '2012-01-01' and '2012-03-07')
GROUP BY `id`
) b ON a.`id` = b.`id`
WHERE (volume_units = 'Lbs') AND
(`date` between '2012-01-01' and '2012-03-07')
GROUP BY `id`
) s
this is a cross join with no visible condition on the join, i don't think you meant that
if you want to sum quantities you don't need to join at all, just group as zerkms did
You can simply group by date and volume_units without self-join.
SELECT date, volume_units, sum(volume) sum_vol
FROM receving
WHERE date between "2012-01-01" and "2012-03-07"
GROUP BY date, volume_units
Sample test:
select d, vol_units, sum(vol) sum_vol
from
(
select 1 id, '2012-03-07' d, 1 vol, 'lbs' vol_units
union
select 2 id, '2012-03-07' d, 2 vol, 'Gals' vol_units
union
select 3 id, '2012-03-08' d, 1 vol, 'lbs' vol_units
union
select 4 id, '2012-03-08' d, 2 vol, 'Gals' vol_units
union
select 5 id, '2012-03-07' d, 10 vol, 'lbs' vol_units
) t
group by d, vol_units
The query below gives me a report of items that are out for an equipment rental company. this is a super complicated query that takes almost 20 seconds to run. This is obviously not the correct way to get the data that I'm looking for. I build this query from PHP and add in the start date of 02-01-2011 and the end date of 03-01-2011, the product code (p_code = 1) and product pool (i_pool =1). Those 4 pieces of information are passed to a PHP function and injected into the following sql to return the report I need for a calendar control displaying how many items are out. My question is: Is there any way to simplify or do this better, or run more efficiently, using better joins or a better way to display the individual days.
SELECT DISTINCT reportdays.reportday, count(*)
FROM
(SELECT '2011-02-01' + INTERVAL a + b DAY reportday
FROM
(SELECT 0 a UNION SELECT 1 a UNION SELECT 2 UNION SELECT 3
UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7
UNION SELECT 8 UNION SELECT 9 ) d,
(SELECT 0 b UNION SELECT 10 UNION SELECT 20
UNION SELECT 30 UNION SELECT 40) m
WHERE '2011-02-01' + INTERVAL a + b DAY < '2011-03-01'
ORDER BY a + b) as reportdays
JOIN rental_inv as line
ON DATE(FROM_UNIXTIME(line.ri_delivery_dte)) <= reportdays.reportday
AND DATE(FROM_UNIXTIME(line.ri_pickup_dte)) >= reportdays.reportday
LEFT OUTER JOIN rental_in as rent on line.ri_num = rent.ri_num
LEFT OUTER JOIN rental_cancels cancelled on rent.ri_num = cancelled.ri_num
LEFT OUTER JOIN inv inventory on line.i_num = inventory.i_num
LEFT OUTER JOIN product ON inventory.p_code = product.p_code
WHERE rent.ri_extend = 0 -- disregard extended rentals
AND cancelled.ri_num is null -- disregard cancelled rentals
AND inventory.p_code = 1
AND inventory.i_pool = 1
GROUP BY reportdays.reportday
If there is any other information needed, let me know and I'll post it.
You can use:
SELECT DATE(ri_delivery) as day,
count(*) as itemsout,
FROM rental_inv
GROUP BY day;
I'm not sure if you need this or a different thing.
SELECT dates.day, count (*)
FROM rental_inv line
INNER JOIN (SELECT DATE(ri_delivery_dte) as day FROM rental_inv
WHERE ri_delivery_dte >= '2011/02/01'
AND ri_delivery_dte <= '2011/02/28'
GROUP BY day
UNION
SELECT DATE(ri_pickup_dte) as day FROM rental_inv
WHERE ri_pickup_dte >= '2011/02/01'
AND ri_pickup_dte <= '2011/02/28'
GROUP BY day) dates
ON line.ri_delivery_dte <= dates.day and line.ri_pickup_dte >= dates.day
LEFT JOIN rental_cancels canc on line.ri_num = canc.ri_num
LEFT JOIN rental_in rent on line.ri_num = rent.ri_num
WHERE canc.ri_num is null
AND rent.ri_extend = 0
GROUP BY dates.day
to find all days:
SELECT DATE(IFNULL(ri_delivery,ri_pickup)) AS date FROM rental_inv AS dateindex WHERE [YEAR-MONTH-1] <= ri_delivery <= LAST_DAY([YEAR-MONTH-1]) OR [YEAR-MONTH-1] <= ri_pickup <= LAST_DAY([YEAR-MONTH-1]) GROUP BY date HAVING NOT ISNULL(date)
to find items out
SELECT COUNT(id) FROM rental_inv WHERE ri_pickup = [DATE];
to find items in
SELECT COUNT(id) FROM rental_inv WHERE ri_delivery = [DATE];
to find balance
SELECT COUNT(out.id) - COUNT(in.id) FROM rental_inv AS out INNER JOIN rental_inv AS in
ON DATE(out.ri_pickup) = DATE(in.ri_delivery) WHERE out.ri_pickup = [DATE] OR in.ri_delivery = [DATE]
You probably can join up everything but since its procedure its more clear;
I am not sure if this would be the exact answer to your problem but I would do something like this I guess. (I didn't use any SQL editor so u need to check syntax I guess)
SELECT
reportdays.d3 as d,
( COALESCE(outgoing.c1,0) - COALESCE(incoming.c2,0) ) as c
FROM
-- get report dates
(
SELECT DATE(FROM_UNIXTIME(COALESCE(l3.ri_delivery_dte, l3.ri_pickup_dte)) d3
FROM rental_inv l3
WHERE
(l3.ri_delivery_dte >= UNIX_TIMESTAMP('2011-02-01')
AND l3.ri_delivery_dte < UNIX_TIMESTAMP('2011-03-01'))
OR (l3.ri_pickup_dte >= UNIX_TIMESTAMP('2011-02-01')
AND l3.ri_pickup_dte < UNIX_TIMESTAMP('2011-03-01'))
GROUP BY d3
) as reportdays
-- get outgoing
LEFT JOIN (
SELECT DATE(FROM_UNIXTIME(l1.ri_delivery_dte)) as d1, count(*) as c1
FROM rental_inv l1
LEFT JOIN rental_cancels canc1 on l.ri_num = canc1.ri_num
LEFT JOIN rental_in rent1 on l.ri_num = rent1.ri_num
WHERE
l1.ri_delivery_dte >= UNIX_TIMESTAMP('2011-02-01')
AND l1.ri_delivery_dte < UNIX_TIMESTAMP('2011-03-01')
AND canc1.ri_num is null
AND rent1.ri_extend = 0
GROUP BY d1
) as outgoing ON reportdays.d3 = outgoing.d1
-- get incoming
LEFT JOIN (
SELECT DATE(FROM_UNIXTIME(l2.ri_pickup_dte)) as d2, count(*) as c2
FROM rental_inv l2
LEFT JOIN rental_cancels canc2 on l2.ri_num = canc2.ri_num
LEFT JOIN rental_in rent2 on l2.ri_num = rent2.ri_num
WHERE
l2.ri_pickup_dte >= UNIX_TIMESTAMP('2011-02-01')
AND l2.ri_pickup_dte < UNIX_TIMESTAMP('2011-03-01')
AND canc2.ri_num is null
AND rent2.ri_extend = 0
GROUP BY d2
) as incoming ON reportdays.d3 = incoming.d2