i am very new to programming and now i have problem to solve it quickly. Trying for 1weeks only and give some result that can satisfy me. Any one can help me with this, heres my table and result that i wanted to show:
enter image description here
this the result
the problem ss
i am trying and trying this code for more than a weeks and its still nothing:
enter code here SELECT idkt.id,
idkt.nama,
idkt.satuan,
trgt.nilai ,
tbl.*,
ROUND((tbl.Triwulan_1 / trgt.nilai * 100), 2) Persen_1,
ROUND((tbl.Triwulan_2 / trgt.nilai * 100), 2) Persen_2,
ROUND((tbl.Triwulan_3 / trgt.nilai * 100), 2) Persen_3,
ROUND((tbl.Triwulan_4 / trgt.nilai * 100), 2) Persen_4
FROM indikator idkt
left JOIN (
SELECT id_indikator,
YEAR(tgl) tahun,
SUM(CASE
WHEN MONTH(tgl) BETWEEN 1 AND 3 THEN
1
END) AS Triwulan_1,
SUM(CASE
WHEN MONTH(tgl) BETWEEN 4 AND 6 THEN
1
END) AS Triwulan_2,
SUM(CASE
WHEN MONTH(tgl) BETWEEN 7 AND 9 THEN
1
END) AS Triwulan_3,
SUM(CASE
WHEN MONTH(tgl) BETWEEN 10 AND 12 THEN
1
END) AS Triwulan_4
FROM msttrans
WHERE YEAR(tgl) = ".$tahun."
GROUP BY id_indikator, YEAR(tgl)) tbl
ON (idkt.id = tbl.id_indikator)
left JOIN target trgt
ON (trgt.id_indikator = idkt.id
AND YEAR(trgt.tahun) = tbl.tahun)
left JOIN (select target.nilai as fnilai from target where id_indikator is not NULL) trgt on trgt.id_indikator = idkt.id
ORDER BY idkt.id ASC
If any inputs to arithmetic expressions like
ROUND((tbl.Triwulan_1 / trgt.nilai * 100), 2)
are null, the resulting expression will also be null. You probably should try changing these sorts of expressions from
SUM(CASE WHEN MONTH(tgl) BETWEEN 1 AND 3 THEN 1 END) AS Triwulan_1
to
SUM(CASE WHEN MONTH(tgl) BETWEEN 1 AND 3 THEN 1 ELSE 0 END) AS Triwulan_1
to avoid too many attempts to work with null values.
Also, you should troubleshoot by testing your inner queries one-by-one. Make sure they work (especially the one containing GROUP BY) before you use it in a join.
Edit LEFT JOIN operations with ON conditions that don't match any rows return null values for the columns in the left table. This is a common source of unexpected null values. (If you use JOIN in place of LEFT JOIN the query suppresses rows from the right table if they don't match the left table.)
You could troubleshoot these nulls with expressions like this.
SELECT ... tbl.Triwulan_1, trgt.nilai, ROUND((tbl.Triwulan_1 / trgt.nilai * 100), 2), ...
Related
I need your help to optimize the query ,I am using mysql mariadb.The job of the query is to get some datas for using ui.
I set to null some datas because of example. The query is:
select q.*,
(case when q.numberofcustomizations > 0 then 1 else 0 end) hascustomization,
concat_ws(' - ', q.productname, q.variant) productnamewithvariant
from (
select ca.lastname,
oh.orderid,
oh.orderno,
oh.datecreated,
p.productid, concat_ws(' ', b.name, p.model) as productname,
(case when pv.variantid is not null then concat_ws(' / ', pv.type1, pv.type2) end) variant,
ifnull(concat(' / ',ml.sku), case when pv.variantid is not null then ifnull(concat(' / ',pv.sku),concat(' / ',p.sku)) else concat(' / ',p.sku) end) as sku2,(case when pv.variantid is not null then ifnull(concat(' / ',pv.barcode),concat(' / ',p.barcode)) else concat(' / ',p.barcode) end) as barcode2,
ml.uuid, ml.merchantwarehouseid,
p.sku,
mo.lineid as merchantorderid,
mo.orderlineno,mo.pending,
ol.quantity, ol.comment,
ifnull((select sum(numberofitemshipped) from merchant_order_shipment mos where mos.merchantorderlineid=mo.lineid),0) as numberofitemshipped,
ifnull((select sum(numberofitemshipped) from merchant_order_shipment mos where mos.merchantorderlineid=mo.lineid and mos.`status`='delivered'),0) as numberofitemdelivered,
ol.price,
ol.bundlecode,
concat_ws(' ',bb.name, pb.model) as bundleproductname,
mo.statuscode,
os.isopenorder,
os.name as status, p.barcode,
p.manufactureritemcode,
r.fullsizeurl,
r.thumbnailsizeurl,
sa.postalcode as shipping_postalcode,
sa.countrycode as shipping_countrycode,
(select count(0) from order_line_property olp where olp.orderid=mo.orderid and olp.lineno=mo.orderlineno) numberofcustomizations,
(select count(0) from order_line_property olp where olp.orderid=mo.orderid and olp.lineno=mo.orderlineno and olp.value is null) numberofcustomizationrequests,
case when exists(select null from order_incident oi where oi.orderid=mo.orderid and oi.orderlineno=mo.orderlineno) then 1 else 0 end hasincident,
(ifnull((select sum(ols.price) from order_line ols where ols.orderid=oh.orderid and ols.feetypecode='shipment'),0) / (select count(distinct pm.merchantid) from order_line olm join product pm on pm.productid=olm.productid where olm.orderid=oh.orderid) ) as shippingfee,
(case when olg.giftfrom is not null then 1 else 0 end) hasgiftnote
from merchant_order mo
join merchant_listing ml on ml.merchantlistingid=mo.merchantlistingid
join order_header oh on oh.orderid=mo.orderid
join address sa on sa.addressid=oh.addressid
join order_line ol on ol.orderid=oh.orderid and ol.lineno=mo.orderlineno
join order_status os on os.statuscode=mo.statuscode and os.isvalidorder=1
join product p on p.productid=ol.productid
join customer c on c.customerid=oh.customerid
join address ca on ca.addressid=c.addressid
left outer join product_variant pv on pv.variantid=ml.variantid
left outer join brand b on b.brandid=p.brandid
left outer join product_resource pr on pr.productid=p.productid and pr.isdefault=1
left outer join resource r on r.resourceid=pr.resourceid
left outer join order_line_gift olg on olg.orderid=mo.orderid and olg.lineno=mo.orderlineno
left outer join category cat on cat.categoryid=p.categoryid
left outer join product pb on pb.bundlecode=ol.bundlecode
left outer join brand bb on bb.brandid=pb.brandid
join (select #categoryid=NULL, #brandid=NULL, #merchantwarehouseid=NULL, #hascustomization=NULL, #iscustomizationrequested=NULL, #hassuborder=NULL) params on 1=1
where
mo.statuscode=ifnull(NULL,mo.statuscode)
and oh.orderno=ifnull(NULL, oh.orderno)
and c.customerno=ifnull(NULL, c.customerno)
and ca.firstname=ifnull(NULL, ca.firstname)
and ca.lastname=ifnull(NULL, ca.lastname)
and ca.email=ifnull(NULL, ca.email)
and ml.productid=ifnull(NULL, ml.productid)
and (case when #categoryid is null then 1
when cat.categoryid=#categoryid then 1
when cat.overcategoryid=#categoryid then 1 end)
and (case when #brandid is null then 1
when p.brandid=#brandid and b.isactive=1 then 1
end)
and (case when #merchantwarehouseid is null then 1
when ml.merchantwarehouseid=#merchantwarehouseid then 1 end)
and concat(ifnull(oh.originref,'-'),' / ',ifnull(oh.originsource,'-'))=ifnull(NULL,concat(ifnull(oh.originref,'-'),' / ',ifnull(oh.originsource,'-')))
and mo.pending=ifnull(NULL, mo.pending)
and oh.datecreated between ifnull(NULL, oh.datecreated) and ifnull(NULL, oh.datecreated)
) q
where
(case when #hascustomization is null then 1
when q.numberofcustomizations > 0 and #hascustomization = 1 then 1
when q.numberofcustomizations = 0 and #hascustomization = 0 then 1
end)
and (case when #iscustomizationrequested is null then 1
when q.numberofcustomizationrequests > 0 and #iscustomizationrequested = 1 then 1
when q.numberofcustomizationrequests = 0 and #iscustomizationrequested = 0 then 1
end)
order by 1
Explain cost:
cost
I marked the problematic points in yellow.
Also I added new index for bundlecode,it fixed. But I dont know how to fix first two lines.
Thanks
Some problems!
(1) What is this?? and ca.firstname=ifnull(NULL, ca.firstname). If you don't need the test, build the query without the test.
(2) Avoid #Variables... SET #hascustomization=NULL then WHERE #hascustomization = ... will always fail. That is, NULL is not equal to either 0 or 1.
Don't try to fix that, instead get rid of #variables by constructing the query on the fly. This will [perhaps significantly] help the optimization of the query.
More specifically, get rid of
join
(
SELECT #categoryid=NULL, #brandid=NULL, #merchantwarehouseid=NULL,
#hascustomization=NULL, #iscustomizationrequested=NULL,
#hassuborder=NULL
and then simplify
(case when #hascustomization is null then 1 when q.numberofcustomizations > 0
and #hascustomization = 1 then 1 when q.numberofcustomizations = 0
and #hascustomization = 0 then 1 end
)
(etc)
(3) When you get to putting the pagination back in, rewrite the query. Having all the JOINs before doing the pagination is quite inefficient. Instead, do the minimal effort to find the next, say, 10 IDs, then do the JOINs to get the rest of the info -- this time looking up only 10 items for each JOIN.
(4) After all that, start a new Question showing the revised query; I will make suggestions of indexes (often 'composite') to further improve performance. Be sure to include SHOW CREATE TABLE and EXPLAIN SELECT ... in that Question.
I have a table with 5 fields
id = this is autoincrementing field
form_id = this field is the form being filled out
entry_id = this is the identifier of the entry
meta_key = this is the identifier of the specific form fields
meta_value = this is the value entered into the form field
If I do a:
SELECT SUM(meta_value) FROM tbl WHERE meta_key = 55;
I get the sum of all the people who like apples.
If I do a:
SELECT SUM(meta_value) FROM tbl WHERE meta_key = 75;
I get the sum of all the people total.
I am trying to write one query that will give me the % of people who like apple so in essence ((RESULT of Q1) / (RESULT of Q2)) * 100
So far I've looked into self joins and subqueries but I'm essentially stuck now because all the tutorials on subqueries focus on the WHERE clause.
Simplest thing I can think of:
SELECT
(SELECT SUM(meta_value) FROM tbl WHERE meta_key = 55) /
(SELECT SUM(meta_value) FROM tbl WHERE meta_key = 75) * 100
as percentage;
Would that work for you?
You can try this query, it avoid any possibility of division by zero, just in case total = 0.
SELECT
CASE
WHEN b.sum_b IS NULL OR b.sum_b = 0 THEN 0
ELSE (a.sum_a / b.sum_b) * 100
END as percent
FROM (
SELECT SUM(meta_value) as sum_a FROM tbl WHERE meta_key = 55
) a,
(
SELECT SUM(meta_value) as sum_b FROM tbl WHERE meta_key = 75
) b
You can use conditional aggregation
SELECT (SUM(CASE WHEN meta_key = 55 THEN meta_value ELSE 0 END) /
SUM(CASE WHEN meta_key = 75 THEN meta_value ELSE 0 END)) * 100 -- be careful you may got divide by zero error
FROM tbl
WHERE meta_key IN (55, 75);
However, this would produce integer division result. So, you can include 1.0 before division if you want exact result.
To avoid division by zero, I would simply recommend:
SELECT (SUM(CASE WHEN meta_key = 55 THEN meta_value ELSE 0 END) /
SUM(CASE WHEN meta_key = 75 THEN meta_value END)
) * 100
FROM tbl
WHERE meta_key IN (55, 75);
Note that the second CASE has no ELSE. If there are no matches, then this returns NULL, avoiding the divide-by-zero.
That said, MySQL does not return an error for divide-by-zero. It simply returns NULL. But that is highly database-specific behavior. I think every other database returns an error and you should be conscious of such potential issues.
I'm creating a rating system. I have two tables hinne (rating) and hinnang (rating multiplier). I need to multiply the rating and then average the rating to know what rating I got out of all ratings by aine(subject).
Example:
All points need to be calculated in 0-100 point system.
So if my first rate is 25 and the rating multiplier is 4 then first rate (25/25)
4*25=100
If the second rate is 30 and multiplier 2 then second rate (30/50)
2*30=60
Now I need to average them like 100+60/2=80.
That should work in my SQL statement, but I got in trouble.
CASE
WHEN aine.nimetus = 'Füüsika I'
THEN hinne.tulemus * hindamine.kaal
ELSE 0
END
,0)
))
So, this is my pivot case statement. hindamine.kaal should be different value for each hinne.tulemus 25*4,50*2 BUT it doesn't work. It just uses multiplier value 4. How can I make this work?
The result of SQL: 150
The expected result: 100
Therefore here is my full SQL:
SELECT
tudeng.m_number,hindamine.kaal, ROUND(AVG(NULLIF(
CASE
WHEN aine.nimetus = 'Füüsika I'
THEN hinne.tulemus * hindamine.kaal
ELSE 0
END
,0)
))
AS FüüsikaI ,ROUND(AVG(NULLIF(
CASE
WHEN aine.nimetus = 'Kõrgem matemaatika I'
THEN hinne.tulemus * hindamine.kaal
ELSE 0
END
,0)
))
AS KõrgemmatemaatikaI ,ROUND(AVG(NULLIF(
CASE
WHEN aine.nimetus = 'Raalprojekteerimine'
THEN hinne.tulemus * hindamine.kaal
ELSE 0
END
,0)
))
AS Raalprojekteerimine ,ROUND(AVG(NULLIF(
CASE
WHEN aine.nimetus = 'Tehniline graafika'
THEN hinne.tulemus * hindamine.kaal
ELSE 0
END
,0)
))
AS Tehnilinegraafika , ROUND(AVG(NULLIF(
CASE
WHEN aine.nimetus = 'Ettevõteluse alused'
THEN hinne.tulemus * hindamine.kaal
ELSE 0
END
,0)
))
AS Ettevõtelusealused
FROM
tudeng
INNER JOIN
aine_tudeng
ON
tudeng.tudeng_id = aine_tudeng.tudeng_id
INNER JOIN
aine
ON
aine.aine_id = aine_tudeng.aine_id
INNER JOIN
hinne
ON
hinne.aine_tudeng_id=aine_tudeng.aine_tudeng_id
INNER JOIN
hindamine
ON
hindamine.hindamine_id=aine_tudeng.aine_id
GROUP BY
tudeng.m_number
I suppose your error is here:
ON hindamine.hindamine_id = aine_tudeng.aine_id
A hindamine (assessment/rating?) is something different from an aine (subject?), so you are mistaken in joining on these IDs.
(I have used Google translator to help me with the meanings.)
In my current query:
SELECT COUNT(WC.ID) AS "Regions"
FROM WHOLE_FEATURES_PDB_CHAINS AS WC
;
I COUNT(WC.ID) AS "Regions" .
However, we have multiple regions with WC.Type can be 1,2,3,4. I need to count each type occurrence into COUNT(WC.ID) AS "Region_1", COUNT(WC.ID) AS "Region_2" ... depending on WC.Type.
Is there any way to solve this in one query? I am looking at MySQL IF, yet do not know how to integrate it into the count function.
I need it to be in one row (the shown query here is reduced, it's a larger query)
SELECT COUNT(WC.ID) AS "Region_1" , COUNT(WC.ID) AS "Region_2" ...
Here is the complete query if anyone is interested:
SELECT PCS.PDB_id, PCS.Chain, PPA.ENSEMBL_start, PPA.ENSEMBL_end, PPA.eValue, PIN.TITLE AS "pdbTitle", COUNT(WC.ID) AS "Regions"
FROM PDB_Chains AS PCS
LEFT JOIN WHOLE_FEATURES_PDB_CHAINS AS WC ON WC.PDB_CHAIN_ID = PCS.idPDB_chains, PDB_protein_alignment PPA, PDB_INFOS PIN
WHERE PCS.idPDB_chains = PPA.idPDB_Chains
AND PCS.PDB_id = PIN.PDB_ID
AND PPA.idProteins = (SELECT idProteins from Proteins WHERE ENSEMBL_protein_id = "'+submittedID+'")
GROUP BY PCS.PDB_id, PCS.Chain ORDER BY PCS.PDB_id;
Here's the working solutin based on your kind answers
SELECT PIN.TITLE AS "pdbTitle", COUNT(CASE WHEN WC.STRUCTURAL_FEATURES_ID = 1 then 1 end) AS "PPInterface" , COUNT(CASE WHEN WC.STRUCTURAL_FEATURES_ID = 4 then 1 end) AS "flexibleRegions"
FROM PDB_Chains AS PCS LEFT JOIN WHOLE_FEATURES_PDB_CHAINS AS WC ON WC.PDB_CHAIN_ID = PCS.idPDB_chains, PDB_protein_alignment PPA, PDB_INFOS PIN
WHERE PCS.idPDB_chains = PPA.idPDB_Chains
AND PCS.PDB_id = PIN.PDB_ID
AND PPA.idProteins = (SELECT idProteins from Proteins WHERE ENSEMBL_protein_id = "ENSP00000256078.4")
GROUP BY PCS.PDB_id, PCS.Chain ORDER BY PCS.PDB_id;
You can use case when statement inside your aggregate function.
Try this .
count(case when WC.type = 1 then 1 end) as region_1, similarly repeat for another column.
Select
...
...
sum(if WC.ID = 1 then 1 else 0) as Region1,
sum(if WC.ID = 2 then 1 else 0) as Region2,
sum(if WC.ID = 3 then 1 else 0) as Region3,
sum(if WC.ID = 4 then 1 else 0) as Region4
Might do what you want.
You can use GROUP BY with COUNT to get the required result, e.g.:
SELECT WC.Type, COUNT(WC.ID) AS "Regions"
FROM WHOLE_FEATURES_PDB_CHAINS AS WC
GROUP BY WC.Type;
Update
If you want the counts as pivoted column for each region then you can write inner SELECT queries, e.g.:
SELECT
(SELECT COUNT(ID) FROM WHOLE_FEATURES_PDB_CHAINS WHERE type = 1) AS "Region_1",
(SELECT COUNT(ID) FROM WHOLE_FEATURES_PDB_CHAINS WHERE type = 2) AS "Region_2",
other_column
FROM WHOLE_FEATURES_PDB_CHAINS AS WC
WHERE <some condition>;
Considering the following code:
SELECT SUM(w.valor),
SUM(CASE WHEN w.tipo = '+' THEN w.valor ELSE 0 END) AS total_credit,
SUM(CASE WHEN w.tipo = '-' THEN w.valor ELSE 0 END) AS total_debit,
w.clientUNIQUE,
c.client as cclient
FROM wallet AS w
LEFT JOIN clients AS c ON w.clientUNIQUE = c.clientUNIQUE
WHERE w.status='V'
GROUP BY w.clientUNIQUE
ORDER BY total_credit-total_debit
I'm trying to calculate the difference of two aliased calculated values for sorting purposes, but I'm getting the following error:
Reference 'total_credit' not supported (reference to group function)
What am I doing wrong and how can I order results by using the difference value between the two aliases?
You can't refer to columns by their alias in the same select expression, so there are 2 options...
Repeat the expressions in the order by (yuk):
ORDER BY
SUM(CASE WHEN w.tipo = '+' THEN w.valor ELSE 0 END) AS total_credit -
SUM(CASE WHEN w.tipo = '-' THEN w.valor ELSE 0 END) AS total_debit
Or easier on the brain and easier to maintain (DRY), order via a sub query:
select * from (
<your query without the ORDER BY>
) q
ORDER BY total_credit - total_debit