MySQL query:
SELECT SUM(t.transactionAmt) as transactionAmt, c.categoryType, MONTH(str_to_date(t.transactionDate, '%d/%m/%Y')) as transactionMonth, YEAR(str_to_date(t.transactionDate, '%d/%m/%Y')) as transactionYear
FROM transaction_db t INNER JOIN category_db c
ON t.categoryID = c.categoryID
WHERE t.accountID = '12'
GROUP BY c.categoryType, MONTH(str_to_date(t.transactionDate, '%d/%m/%Y'))
ORDER BY MONTH(str_to_date(t.transactionDate, '%d/%m/%Y')) DESC
This is the output:
Is there any way to query it in such a way such that if there are from same transactionMonth, I take the row with categoryType 0 minus away the row with categoryType 1?
For instance, for month 5, I take the 2233 subtract with 464 to get the result.
Thanks in advance!
You can create a view from your query (see Create VIEW Syntax for details), that will be used in subqueries:
SELECT
cat1.transactionAmt - cat2.transactionAmt AS transactionDiff
FROM
(SELECT * FROM MyView WHERE categoryType = 0) AS cat1
JOIN
(SELECT * FROM MyView AS cat1 WHERE categoryType = 1) AS cat2
USING(transactionMonth);
Or try to use Control Flow Functions. For example:
SELECT
SUM(IF(c.categoryType=0, t.transactionAmt, -t.transactionAmt)) as transactionAmt,
MONTH(str_to_date(t.transactionDate, '%d/%m/%Y')) as transactionMonth,
YEAR(str_to_date(t.transactionDate, '%d/%m/%Y')) as transactionYear
FROM
transaction_db t INNER JOIN category_db c
ON t.categoryID = c.categoryID
WHERE t.accountID = '12'
GROUP BY MONTH(str_to_date(t.transactionDate, '%d/%m/%Y'))
ORDER BY MONTH(str_to_date(t.transactionDate, '%d/%m/%Y')) DESC
Related
this is sample data in table pengiriman_supply.
and this is for data_barang
this is for data_supplier and table masuk.
if I'm not using 3 tables the sum is no a problem but if I'm using 4 tables and using subtraction with (sum(table1.a)-ifnull(table2.b)). here is the result with just sum
and this is the picture with subtraction
the code is like this
SELECT DISTINCT
row_number() over(
order by pengiriman_supply.po_nomor desc) as no,
pengiriman_supply.po_nomor as PO,
data_supplier.nama_supplier,
data_barang.nama_barang,
((sum( pengiriman_supply.jumlah ))- (sum( COALESCE ( masuk.terima, 0 )) over ( PARTITION BY masuk.refrence ))) as total
FROM
pengiriman_supply
LEFT JOIN masuk ON pengiriman_supply.po_nomor = masuk.refrence
INNER JOIN data_supplier ON data_supplier.id_supplier = pengiriman_supply.idsupplier
INNER JOIN data_barang ON data_barang.idbarang = pengiriman_supply.idbarang
WHERE
pengiriman_supply.tanggal between date_sub(curdate(), interval 60 day) and curdate()
GROUP BY
pengiriman_supply.po_nomor,masuk.po_nomor,data_supplier.nama_supplier
ORDER BY
GROUP_CONCAT(DISTINCT pengiriman_supply.po_nomor) DESC
this the code that SQL statement that I can find. but the group by not make the SQL statement just pengiriman_supply.po_nomor. can I make the group by just the pengiriman_supply.po_nomor .
can the number 31194 make in one group?
it seems you need to include ifnull(masuk.terima,0) inside sum()
SELECT
pengiriman_supply.po_nomor AS po,
data_supplier.nama_supplier,
data_barang.nama_barang,
Sum((pengiriman_supply.jumlah)-ifnull(masuk.terima,0)) as total
FROM
pengiriman_supply
INNER JOIN data_barang ON pengiriman_supply.idbarang = data_barang.idbarang
INNER JOIN data_supplier ON pengiriman_supply.idsupplier = data_supplier.id_supplier
LEFT JOIN masuk ON masuk.refrence = pengiriman_supply.po_nomor
GROUP BY
pengiriman_supply.po_nomor
ORDER BY
po DESC
I've had troubles when trying to combine the result of 3 queries:
It's the result of 3 queries joined with union, they all pick datas in the same tables except for the last column and I'd like to have the result in one row, which would give me the result 17 in this case but I can't make it works...Any ideas?
thanks
edit: here is the code of the 3 queries used with union from the result above:
select distinct SSN_ID,
TME_ID,
TME_LIBELLE,
convert(varchar,ssn_date_debut,103) as 'Debut',
CONVERT (varchar,ssn_date_fin,103) as 'Fin',
SSN_NB_JOURS,
COUNT (atr_id) as 'Total'
from SESSION
join INSCRIPTION on INS_SSN_ID = SSN_ID
join ACTEUR on INS_ATR_ID = ATR_ID
join theme on tme_id = ssn_tme_id
join ETAT_SESSION on esn_id = ssn_esn_id
join LIEU_SESSION on LSN_SSN_ID =ssn_id
join LIEU on LEU_ID = LSN_LEU_ID
where INS_DT_CONVOCATION is not null
and SSN_ESN_ID = 15
and SSN_JOURNEE_ETUDE = 1
and LEU_NOM is not null
and year(ssn_date_debut) = YEAR(GETDATE())
group by SSN_ID,TME_ID,TME_LIBELLE,ssn_date_debut,ssn_date_fin,SSN_NB_JOURS,ins_ssn_id
union
select distinct SSN_ID,
TME_ID,
TME_LIBELLE,
convert(varchar,ssn_date_debut,103) as 'Debut',
CONVERT (varchar,ssn_date_fin,103) as 'Fin',
SSN_NB_JOURS,
COUNT (atr_id) as 'Total'
from SESSION
join SESSION_FORMATEUR on ASN_SSN_ID = SSN_ID
join ACTEUR anim on anim.ATR_ID = asn_atr_id
join theme on tme_id = ssn_tme_id
join ETAT_SESSION on esn_id = ssn_esn_id
join LIEU_SESSION on LSN_SSN_ID =ssn_id
join LIEU on LEU_ID = LSN_LEU_ID
where SSN_ESN_ID = 15
and SSN_JOURNEE_ETUDE = 1
and LEU_NOM is not null
and year(ssn_date_debut) = YEAR(GETDATE())
group by SSN_ID, TME_ID,
TME_LIBELLE,ssn_date_debut,ssn_date_fin,SSN_NB_JOURS,asn_ssn_id
union
select distinct SSN_ID,
TME_ID,
TME_LIBELLE,
convert(varchar,ssn_date_debut,103) as 'Debut',
CONVERT (varchar,ssn_date_fin,103) as 'Fin',
SSN_NB_JOURS,
COUNT (atr_id) as 'Total'
from SESSION
left join INTERVENANT on ITV_SSN_ID = SSN_ID
left join ACTEUR on ITV_ATR_ID = ATR_ID
join theme on tme_id = ssn_tme_id
join ETAT_SESSION on esn_id = ssn_esn_id
join LIEU_SESSION on LSN_SSN_ID =ssn_id
join LIEU on LEU_ID = LSN_LEU_ID
where SSN_ESN_ID = 15
and SSN_JOURNEE_ETUDE = 1
and LEU_NOM is not null
and year(ssn_date_debut) = YEAR(GETDATE())
group by SSN_ID, TME_ID,
TME_LIBELLE,ssn_date_debut,ssn_date_fin,SSN_NB_JOURS,ITV_SSN_ID
A derived query approach to get SUM on a total column:
SELECT SSN_ID, TIME_ID, TIME_LIBELLE, DEBUT, FIN, SSN_NB_JOURS, SUM(Total) as Total
FROM
(
-- Your original SELECT with UNION
SELECT .. FROM ..
UNION ALL
SELECT .. FROM ..
UNION ALL
SELECT .. FROM ..
) d
GROUP BY SSN_ID, TIME_id, TIME_LIBELLE, DEBUT, FIN, SSN_NB_JOURS
Such way should be a valid syntax on both: mysql and sql server
Use as
select(
select distinct (all columns except the last one) from table) , (select sum(total) from table)
I have a query where I do a join on a substring, the problem is that this is really slow to complete. Is there a more effecient way to write this?
SELECT *, SUM(s.pris*s.antall) AS total, SUM(s.antall) AS antall
FROM ecs_statistikk AS s
JOIN butikk_ordre AS bo ON ordreId=bo.ecs_ordre_id AND butikkNr=bo.site_id
JOIN ecs_supplier AS l ON SUBSTRING( s.artikkelId, 1,2 )=l.lev_id
WHERE s.salgsDato>='2016-6-01' AND s.salgsDato<='2016-09-30'
GROUP BY l.lev_id ORDER BY total DESC
First, I would check indexes. For this query:
SELECT *, SUM(s.pris*s.antall) AS total, SUM(s.antall) AS antall
FROM ecs_statistikk s JOIN
butikk_ordre bo
ON s.ordreId = bo.ecs_ordre_id AND
s.butikkNr = bo.site_id JOIN
ecs_supplier l
ON SUBSTRING(s.artikkelId, 1, 2 ) = l.lev_id
WHERE s.salgsDato >= '2016-06-01' AND s.salgsDato <= '2016-09-30'
GROUP BY l.lev_id
ORDER BY total DESC ;
You want indexes on ecs_statistikk(salgsDato, ordreId, butikkNr, artikkelId), butikk_ordre(ecs_ordre_id, site_id), and ecs_supplier(lev_id)`.
Next, I would question whether you need the last JOIN at all. Does this do what you want?
SELECT LEFT(s.artikkelId, 2) as lev_id, *,
SUM(s.pris*s.antall) AS total, SUM(s.antall) AS antall
FROM ecs_statistikk s JOIN
butikk_ordre bo
ON s.ordreId = bo.ecs_ordre_id AND
s.butikkNr = bo.site_id
WHERE s.salgsDato >= '2016-06-01' AND s.salgsDato <= '2016-09-30'
GROUP BY LEFT(s.artikkelId, 2)
ORDER BY total DESC ;
I have two queries giving two sets of result, i want to divide one query's result with another.
Here is my first query :
SELECT COUNT(*)
FROM survey_event_answers a JOIN survey_events e ON a.eventid = e.eventid
WHERE e.event_status = 'Closed' AND
e.survey_date BETWEEN '2013-05-01' AND '2014-01-31' AND
a.response_options IN (10,11) AND a.questionid = 7
GROUP BY MONTH(e.survey_date) DESC;
Here is the result of this query :
279
443
664
743
785
1312
1085
915
231
Here is my another query :
SELECT COUNT(*),e.survey_date
FROM `survey_event_answers` a INNER JOIN survey_events e ON a.eventid = e.eventid
WHERE e.event_status='Closed' AND
e.survey_date BETWEEN '2013-05-01' AND '2014-01-31' AND
a.questionid=7
GROUP BY MONTH(e.survey_date) DESC
Here is the query result :
351
539
826
926
984
1654
1378
1165
844
I want that first row of first result set should divide by first row of second row set.
Please help me out how can i do this.
Thanks
is this what are you looking for?
SELECT rd1.r1/rd2.r2 `result`
FROM (
SELECT COUNT(*) r1,MONTH(e.survey_date) d1
FROM `survey_event_answers` a
INNER JOIN survey_events e
ON (a.eventid = e.eventid)
WHERE e.event_status='Closed' AND e.survey_date BETWEEN '2013-05-01' AND '2014-01-31'
AND a.response_options IN (10,11) AND a.questionid=7
GROUP BY MONTH(e.survey_date) DESC ) rd1
JOIN (
SELECT COUNT(*) r2, MONTH(e.survey_date) d2
FROM `survey_event_answers` a
INNER JOIN survey_events e
ON (a.eventid = e.eventid)
WHERE e.event_status='Closed' AND e.survey_date BETWEEN '2013-05-01' AND '2014-01-31'
AND a.questionid=7
GROUP BY MONTH(e.survey_date) DESC ) rd2
ON rd1.d1=rd2.d2
You could do:
SELECT SUM(IF(a.response_options IN (10,11), 1, 0))/COUNT(*)
FROM survey_event_answers a
JOIN survey_events e
ON a.eventid = e.eventid
WHERE e.event_status = 'Closed'
AND e.survey_date BETWEEN '2013-05-01' AND '2014-01-31'
AND a.questionid = 7
GROUP BY MONTH(e.survey_date) DESC;
This may not be fast (but it is faster than doing the query twice and joining the results), but probably do what you want (ratio of answers 10 or 11). You can add the MONTH(e.survey_date) as a second column.
SELECT
productos.prod_id,
productos.prod_codigo1,
productos.prod_descripcion,
(SELECT SUM(cotdetalle.cotd_cantidad)
FROM cotdetalle
WHERE cotdetalle.cotd_codigo = productos.prod_codigo1
AND cotdetalle.cotd_cote_id IN(
SELECT cotencabezado.cote_id
FROM cotencabezado
WHERE cotencabezado.cote_status = 'cerrada'
AND MONTH(cotencabezado.cote_cierre) = MONTH(NOW()) AND YEAR(cotencabezado.cote_cierre) = YEAR(NOW())
)
) AS cuantos,
(SELECT SUM(cotdetalle.cotd_cantidad * cotdetalle.cotd_precio)
FROM cotdetalle
WHERE cotdetalle.cotd_codigo = productos.prod_codigo1
AND cotdetalle.cotd_cote_id IN(
SELECT cotencabezado.cote_id
FROM cotencabezado
WHERE cotencabezado.cote_status = 'cerrada'
AND MONTH(cotencabezado.cote_cierre) = MONTH(NOW()) AND YEAR(cotencabezado.cote_cierre) = YEAR(NOW())
)
) AS monto
FROM productos
ORDER BY monto DESC
LIMIT 0, 50
Came out with this query last night, I guess my question is: is it too much? I'm pretty sure there are other ways to get the same results without all that nested queries.. It works but it takes some time on my development environment, I bet it will take a lot more on a production environment... Any suggestions?
Please let me know if you need the table structure...
Edit: Actually that second SELECT is what bothers me most, it is exactly the same as the first one but I need that second result, but if I try to get that second result in the first SELECT it give me the "Operand should contain 1 column(s)" error...
A little more info: I need to be able to order by monto, cuantos, productos.prod_codigo1, productos.prod_descripcion
sqlfiddle.com example: http://sqlfiddle.com/#!2/c4391/1
You should do this as a simple join with a group by:
SELECT p.prod_id, p.prod_codigo1, p.prod_descripcion,
t.quantos, t.monto
FROM productos p left outer join
(SELECT cotdetalle.cotd_codigo, SUM(cotdetalle.cotd_cantidad) as quantos,
SUM(cotdetalle.cotd_cantidad * cotdetalle.cotd_precio) as monto
FROM cotdetalle
WHERE cotdetalle.cotd_codigo = productos.prod_codigo1 and
cotdetalle.cotd_cote_id IN
(SELECT cotencabezado.cote_id
FROM cotencabezado
WHERE cotencabezado.cote_status = 'cerrada' and
MONTH(cotencabezado.cote_cierre) = MONTH(NOW()) AND
YEAR(cotencabezado.cote_cierre) = YEAR(NOW()
)
group by cotdetalle.cotd_codigo
) t
on t.cotd_codigo = p.prod_codigo1
ORDER BY monto DESC
LIMIT 0, 50
This should improve things. However, MySQL does a poor job with IN and a subquery. So, instead of "IN" in the subquery, we want to change that to a join. Note the addition of "distinct" in the subquery. This isn't necessary for IN but it is for the join:
SELECT p.prod_id, p.prod_codigo1, p.prod_descripcion,
t.quantos, t.monto
FROM productos p join
(SELECT cd.cotd_codigo, SUM(cd.cotd_cantidad) as quantos,
SUM(cd.cotd_cantidad * cd.cotd_precio) as monto
FROM cotdetalle cd join
(SELECT distinct cc.cote_id
FROM cotencabezado cc
WHERE cc.cote_status = 'cerrada' and
MONTH(cc.cote_cierre) = MONTH(NOW()) AND
YEAR(cc.cote_cierre) = YEAR(NOW()
) cc
on cd.cotd_cote_id = cc.cote_id
group by cd.cotd_codigo
) t
on t.cotd_codigo = p.prod_codigo1
ORDER BY monto DESC
LIMIT 0, 50
I didn't test this on SQL Fiddle, so there may be syntax errors.
Why not simplify the statement as
SELECT productos.prod_id,
productos.prod_codigo1,
productos.prod_descripcion,
( SELECT SUM(cotdetalle.cotd_cantidad) AS cuantos,
SUM(cotdetalle.cotd_cantidad * cotdetalle.cotd_precio) AS monto
FROM cotdetalle
WHERE cotdetalle.cotd_codigo = productos.prod_codigo1
AND cotdetalle.cotd_cote_id IN( SELECT cotencabezado.cote_id
FROM cotencabezado
WHERE cotencabezado.cote_status = 'cerrada'
AND MONTH(cotencabezado.cote_cierre) = MONTH(NOW())
AND YEAR(cotencabezado.cote_cierre) = YEAR(NOW())
)
)
FROM productos
ORDER BY monto DESC
LIMIT 0, 50
Ok, it ended like this:
SELECT p.prod_id, p.prod_codigo1, p.prod_descripcion, t.cuantos, t.monto
FROM productos AS p
LEFT JOIN(
SELECT cd.cotd_codigo,
SUM(cd.cotd_cantidad) AS cuantos,
SUM(cd.cotd_cantidad * cd.cotd_precio) AS monto
FROM cotdetalle AS cd
JOIN(
SELECT DISTINCT ce.cote_id
FROM cotencabezado AS ce
WHERE ce.cote_status = 'cerrada'
AND MONTH(ce.cote_cierre) = MONTH(NOW())
AND YEAR(ce.cote_cierre) = YEAR(NOW())
) AS ce
ON cd.cotd_cote_id = ce.cote_id
GROUP BY cd.cotd_codigo
) AS t
ON cd.cotd_codigo = p.prod_codigo1
ORDER BY monto DESC
LIMIT 0, 50
This works a lot better an it's based on Gordon Linoff's suggestions, Thanks man!