mysql combined table joins - mysql

Thank you for your comments I'll try this from a different angle.
How can this query be written to produce these results?
CompID CompeteID Casting Fishing Total
1 1 265.89 425.56 691.45
1 9 212.31 84.76 285.92
1 7 0.00 285.92 285.92
1 8 0.00 44.52 44.52
ORDER BY Total DESC
SELECT cs.CompID, ic.CompeteID
, MAX(IF(cast.CastType_ID BETWEEN 6 AND 12, cast.Length, 0)) + SUM(IF(cast.CastType_ID < 6, 40 - (cast.Length * 2), 0)) AS 'Casting'
FROM `comp-setup` cs
INNER JOIN `input-competitor` ic
ON cs.CompID = ic.Comp_ID
LEFT JOIN `input-casting` cast
ON cast.Compete_ID = ic.CompeteID
GROUP BY ic.CompeteID
UNION ALL
SELECT cs.CompID, ic.CompeteID
, SUM((iw.Weight * ca.Factor) + '1') AS 'Fishing'
FROM `comp-setup` cs
INNER JOIN `input-competitor` ic
ON cs.CompID = ic.Comp_ID
LEFT JOIN `input-weighin` iw
ON iw.Compete_ID = ic.CompeteID
INNER JOIN `input-catchpoints` ca
ON ca.PointsCatchID = iw.PointsCatch_ID
GROUP BY ic.CompeteID
Results from the above query, I have added break-line and Fishing header to separate data.
CompID CompeteID Casting
1 1 265.89
1 7 0
1 8 0
1 9 212.31
----------------------------------
Fishing
1 1 425.56
1 7 285.92
1 8 44.52
1 9 84.76

Days this has taken me to work out. I found this example today which lead me to this solution, please post if there is a better way? But this does what I need!
SELECT Sub1.CompID, Sub1.CompeteID, Sub2.Casting, Sub1.Fishing, Sub2.Casting + Sub1.Fishing AS Total
FROM
(SELECT cs.CompID, ic.CompeteID, SUM((iw.Weight * ca.Factor) + '1') AS Fishing
FROM `comp-setup` cs
INNER JOIN `input-competitor` ic ON cs.CompID = ic.Comp_ID
INNER JOIN `input-weighin` iw ON iw.Compete_ID = ic.CompeteID
INNER JOIN `input-catchpoints` ca ON ca.PointsCatchID = iw.PointsCatch_ID
INNER JOIN `list-grade` gr ON ic.Grade_ID = gr.GradeID
INNER JOIN `list-division` ld ON ic.Div_ID = ld.DivID
GROUP BY ic.CompeteID) Sub1
INNER JOIN
(SELECT cs.CompID, ic.CompeteID, MAX(IF(cast.CastType_ID BETWEEN 6 AND 12, cast.Length, 0)) + SUM(IF(cast.CastType_ID < 6, 40 - (cast.Length * 2), 0)) AS Casting
FROM `comp-setup` cs
INNER JOIN `input-competitor` ic ON cs.CompID = ic.Comp_ID
LEFT JOIN `input-casting` cast ON cast.Compete_ID = ic.CompeteID
GROUP BY ic.CompeteID) Sub2
ON Sub1.CompeteID = Sub2.CompeteID
ORDER BY Total DESC
Here is the post with the example I needed:
MYSQL LEFT JOIN with GROUP BY

Related

How to merge two queries into a subqueries

I have database like this http://sqlfiddle.com/#!9/e52c43
First query is :
SELECT m.tanggal, sum(mi.qty) as totalMuatan, mi.idPlastik
FROM tblMuatan m
LEFT JOIN tblMuatanIsi mi ON m.idMuatan = mi.idMuatan
WHERE m.tanggal='2020-03-15'
GROUP BY mi.idPlastik
The result is:
tanggal totalMuatan idPlastik
2020-03-15 85 1
2020-03-15 10 2
And second query is :
SELECT s.tanggal, sum(si.qty) as totalStok, si.idPlastik
FROM tblStok s
LEFT JOIN tblStokIsi si ON s.idStok = si.idStok
WHERE s.tanggal = '2020-03-15'
GROUP BY si.idPlastik
The result is :
tanggal totalStok idPlastik
2020-03-15 100 1
2020-03-15 200 2
I want to merge that 2 queries into single query with subquery
tanggal totalStok totalMuatan netTotal idPlastik
2020-03-15 100 85 15 1
2020-03-15 200 10 190 2
How to do the subquery in example above? Thank you for the support
Better to use COALESCE since you're using LEFT JOIN for the tables you are calculating SUM from to avoid no result for the records that have NULL values.
select m.tanggal, t.totalStok, sum(mi.qty) as totalMuatan, coalesce(t.totalStok,0)-coalesce(sum(mi.qty),0) as netTotal, mi.idPlastik
from tblMuatan m
LEFT JOIN tblMuatanIsi mi ON m.idMuatan = mi.idMuatan
JOIN (SELECT s.tanggal, sum(si.qty) as totalStok, si.idPlastik
FROM tblStok s
LEFT JOIN tblStokIsi si ON s.idStok = si.idStok
WHERE s.tanggal='2020-03-15'
GROUP BY s.tanggal,si.idPlastik) t on m.tanggal=t.tanggal and mi.idPlastik = t.idPlastik
group by m.tanggal, t.totalStok,mi.idPlastik
Please try..
SELECT T1.tanggal, T2.totalStok, T1.totalMuatan, (T2.totalStok - T1.totalMuatan), T1.idPlastik
FROM
(SELECT m.tanggal, sum(mi.qty) as totalMuatan, mi.idPlastik
FROM tblMuatan m
LEFT JOIN tblMuatanIsi mi ON m.idMuatan = mi.idMuatan
WHERE m.tanggal='2020-03-15'
GROUP BY mi.idPlastik)
as T1,
(SELECT s.tanggal, sum(si.qty) as totalStok, si.idPlastik
FROM tblStok s
LEFT JOIN tblStokIsi si ON s.idStok = si.idStok
WHERE s.tanggal = '2020-03-15'
GROUP BY si.idPlastik)
as T2
WHERE
T1.tanggal = T2.tanggal;
SELECT a.tanggal,
b.totalstok,
a.totalmuatan,
( totalstok - totalmuatan ) netTotal,
a.idplastik
FROM (SELECT convert(varchar, m.tanggal, 23) tanggal,
Sum(mi.qty) AS totalMuatan,
mi.idplastik
FROM #tblmuatan m
LEFT JOIN #tblmuatanisi mi
ON m.idmuatan = mi.idmuatan
WHERE m.tanggal = 1
GROUP BY mi.idplastik,
convert(varchar, m.tanggal, 23)) a
JOIN (SELECT convert(varchar, s.tanggal, 23) tanggal,
Sum(si.qty) AS totalStok,
si.idplastik
FROM #tblstok s
LEFT JOIN #tblstokisi si
ON s.idstok = si.idstok
WHERE s.tanggal = 1
GROUP BY si.idplastik,
convert(varchar, s.tanggal, 23)) b
ON a.idplastik = b.idplastik

Subquery retunrs more than 1 row issue with JOINS

I am working on one project and facing one issue while using some joins..
I have diff tables and columns like:
tblpackages as a
packagename
packageid
stateid
packageduration
seater_4
seater_7
seater_14
tblstates as b
statename
stateid
tblpackage_packagetypes as c
packagetypeid
packageid
tblpackagetype as d
packagetypeid
packagetypename
tblpackageplaces as e
packageid
placeid
tblplaces as f
placeid
tblpackagedurations as g
packageid
days
hotelid
placeid
tblhotels as h
hotelid
and my query is as:
select a.packagename as packagename, a.packageid as packageid,
a.packageduration as days, a.seater_4, a.seater_7, a.seater_14,
b.statename,
substring_index(GROUP_CONCAT( DISTINCT (select f.placename ) SEPARATOR ',
'),',',4) placename,
substring_index(GROUP_CONCAT( DISTINCT (select d.packagetypename ) SEPARATOR
', '),',',4) packagetypename,
(select sum(g.days) from tblpackagedurations g group by a.packageid )
from tblpackages a
join tblstates b on b.stateid = a.stateid
join tblpackage_packagetypes c on c.packageid = a.packageid
join tblpackagetype d on d.packagetypeid = c.packagetypeid
join tblpackageplaces e on e.packageid = a.packageid
join tblplaces f on f.placeid = e.placeid
join tblpackagedurations g on g.packageid = a.packageid
join tblhotels h on h.hotelid = g.hotelid
where b.statename = 'jammu and kashmir'
group by a.packageid, g.packageid
and the output for days as:
packageid days
**************************
1 10
2 10
3 10
4 10
the value of days in durations as:
packageid days
**************************
1 2
2 2
3 2
4 2
4 2
the output should be
1 2
2 2
3 2
4 4
But its not as per expectation and if change group by from a.package to d i.packageid i got error as subquery returns more than 1 row
IF i have really understood your problem (difficult without see your data) you have to make aggregate function of the field you don't group by:
select a.packagename as packagename, a.packageid as packageid,
sum(a.packageduration) as days, a.seater_4, a.seater_7, a.seater_14,
b.statename,
substring_index(GROUP_CONCAT( DISTINCT (select f.placename ) SEPARATOR ',
'),',',4) placename,
substring_index(GROUP_CONCAT( DISTINCT (select d.packagetypename ) SEPARATOR
', '),',',4) packagetypename,
(select sum(g.days) from tblpackagedurations g group by a.packageid )
from tblpackages a
join tblstates b on b.stateid = a.stateid
join tblpackage_packagetypes c on c.packageid = a.packageid
join tblpackagetype d on d.packagetypeid = c.packagetypeid
join tblpackageplaces e on e.packageid = a.packageid
join tblplaces f on f.placeid = e.placeid
join tblpackagedurations g on g.packageid = a.packageid
join tblhotels h on h.hotelid = g.hotelid
where b.statename = 'jammu and kashmir'
group by a.packageid, g.packageid

get sum of multiple values by months in one table

I have table with query :
SELECT DATENAME(Month,TOPUP.tu_timestamp) AS MonthName, TM.terminal_name,
CAST(ROUND(ISNULL(TOPUP.tu_credit - NC.initial_bal, TOPUP.tu_credit) /
TOPUP.currency_rate, 2) AS decimal(18, 2)) AS
Top_Up_Value
FROM dbfastshosted.dbo.fh_mf_top_up_logs AS TOPUP
INNER JOIN dbo.cdf_terminal_user AS TU ON TOPUP.terminal_user_id =
TU.terminal_user_id
INNER JOIN dbo.cdf_currency AS CR ON TOPUP.currency_id = CR.currency_id
INNER JOIN dbo.cdf_cuid AS CU ON TOPUP.cu_id = CU.cu_id
INNER JOIN dbo.cdf_card_role AS CO ON CO.id = CU.card_role_id
INNER JOIN dbo.cdf_terminal_user_account AS UA ON UA.terminal_user_id =
TU.terminal_user_id
INNER JOIN dbo.cdf_terminal AS TM ON TM.terminal_id = UA.terminal_id
INNER JOIN dbfastshosted.dbo.fh_sales_map AS MA ON MA.tu_log_id =
TOPUP.tu_log_id
LEFT OUTER JOIN dbfastshosted.dbo.fh_mf_new_card_logs AS NC ON
MA.nc_log_id = NC.nc_log_id
WHERE (ISNULL(TOPUP.tu_credit - NC.initial_bal, TOPUP.tu_credit) > 0)
and YEAR(TOPUP.tu_timestamp) = '2017'
AND month(TOPUP.tu_timestamp) = 1
AND TM.terminal_id = 7
GROUP BY TOPUP.tu_log_id,DATENAME(Month,TOPUP.tu_timestamp),
TM.terminal_name,
TOPUP.tu_credit, NC.initial_bal, TOPUP.currency_rate, CU.card_type_id;
MonthName Terminal name Top Up Value
------------------------------------------------------
January Terminal 1 100
January Terminal 1 200
January Terminal 3 150
Feb Terminal 1 250
Feb Terminal 1 160
March Terminal 2 120
March Terminal 3 100
and i would like to have total sums of top up value according to months which look like this:
MonthName Top Up Value
-----------------------------------
January 450
February 410
March 220
-----
Dec
as i am beginner in sql , i dont have idea how to do it. Really need help on these. Thanks!
SELECT DATENAME(Month,TOPUP.tu_timestamp) AS MonthName,
SUM(CAST(ROUND(ISNULL(TOPUP.tu_credit - NC.initial_bal, TOPUP.tu_credit) /
TOPUP.currency_rate, 2) AS decimal(18, 2))) AS
Top_Up_Value
FROM dbfastshosted.dbo.fh_mf_top_up_logs AS TOPUP
INNER JOIN dbo.cdf_terminal_user AS TU ON TOPUP.terminal_user_id =
TU.terminal_user_id
look at your group by statement, the result you posted is displaying lesser number of columns then what you have in your query. Tweak it around and you will get your results
Try this
SELECT DATENAME(Month,TOPUP.tu_timestamp) AS MonthName,
SUM(CAST(ROUND(ISNULL(TOPUP.tu_credit - NC.initial_bal, TOPUP.tu_credit) /
TOPUP.currency_rate, 2) AS decimal(18, 2))) AS
Top_Up_Value
FROM dbfastshosted.dbo.fh_mf_top_up_logs AS TOPUP
INNER JOIN dbo.cdf_terminal_user AS TU ON TOPUP.terminal_user_id =
TU.terminal_user_id
INNER JOIN dbo.cdf_currency AS CR ON TOPUP.currency_id = CR.currency_id
INNER JOIN dbo.cdf_cuid AS CU ON TOPUP.cu_id = CU.cu_id
INNER JOIN dbo.cdf_card_role AS CO ON CO.id = CU.card_role_id
INNER JOIN dbo.cdf_terminal_user_account AS UA ON UA.terminal_user_id =
TU.terminal_user_id
INNER JOIN dbo.cdf_terminal AS TM ON TM.terminal_id = UA.terminal_id
INNER JOIN dbfastshosted.dbo.fh_sales_map AS MA ON MA.tu_log_id =
TOPUP.tu_log_id
LEFT OUTER JOIN dbfastshosted.dbo.fh_mf_new_card_logs AS NC ON
MA.nc_log_id = NC.nc_log_id
WHERE (ISNULL(TOPUP.tu_credit - NC.initial_bal, TOPUP.tu_credit) > 0)
and YEAR(TOPUP.tu_timestamp) = '2017'
AND month(TOPUP.tu_timestamp) = 1
AND TM.terminal_id = 7
GROUP BY DATENAME(Month,TOPUP.tu_timestamp)

MySQL join 3 calculation results

I have 3 different MySQL calculations, which I'd like to join. I need to be able to show lines where a sum may not exist for some column, or some invoice might not have a corporation ID.
I'm trying to get something like:
passport_amount | invoice_amount | balance_amount | corporation_id
------------------------------------------------------------------
345 | 2345 | 56 | 56
So that I can work on these values in my application code by iterating the list once and not fetching data from the database three times, and then iterating three times to combine the values.
SELECT
sum(passports.amount) AS passports_amount,
companies.corporation_id
FROM
passports
INNER JOIN
employees ON ( passports.employee_id = employees.id )
INNER JOIN
companies ON ( employees.company_id = companies.id )
WHERE
((((passports.pass_type IN ('sport','culture','both'))
AND
(MONTH(passports.valid_from) >= 1
AND MONTH(passports.valid_from) <= 9
AND YEAR(passports.valid_from) = year(now())))
AND (passports.removed = 0
AND passports.valid_from <= date('2014-09-29 11:55:26')))
AND (companies.removed = 0)
AND companies.corporation_id IS NOT NULL)
GROUP BY
companies.corporation_id;
SELECT
sum(invoices.amount) AS invoices_amount,
invoices.corporation_id
FROM
invoices
WHERE
((((YEAR(sent_at) = 2014)
AND (invoices.product_type_id IN (2,3,4)))
AND
(invoices.removed = 0
AND invoices.activated = 1))
AND invoices.corporation_id IS NOT NULL)
GROUP BY
invoices.corporation_id;
SELECT
amount AS balance_amount,
business_id AS corporation_id
FROM
invoice_balances
WHERE
business_type = 'Corporation';
You can combine queries for balance and invoice amount using sub select in left join but this will look odd and can be expensive in terms of performance
SELECT
SUM(p.amount) AS passports_amount,
ii.invoices_amount,
b.balance_amount,
c.corporation_id
FROM
passports p
INNER JOIN employees e ON ( p.e = e.id )
INNER JOIN companies c ON ( e.company_id = c.id )
/* Added left join for balance using subselect*/
LEFT JOIN (
SELECT amount AS balance_amount, business_id AS corporation_id
FROM invoice_balances
WHERE business_type = 'Corporation'
) b ON (c.corporation_id = b.corporation_id)
/* Added left join for invoices_amount using subselect*/
LEFT JOIN(
SELECT SUM(i.amount) AS invoices_amount,
i.corporation_id
FROM
invoices i
WHERE
((((YEAR(sent_at) = 2014)
AND (i.product_type_id IN (2,3,4)))
AND (i.removed = 0 AND i.activated = 1)
)
AND i.corporation_id IS NOT NULL)
GROUP BY i.corporation_id
) ii ON(c.corporation_id = ii.corporation_id)
/* end of joins */
WHERE
((((p.pass_type IN ('sport','culture','both'))
AND
(MONTH(p.valid_from) >= 1
AND MONTH(p.valid_from) <= 9
AND YEAR(p.valid_from) = YEAR(NOW())))
AND (p.removed = 0
AND p.valid_from <= DATE('2014-09-29 11:55:26')))
AND (c.removed = 0)
AND c.corporation_id IS NOT NULL)
GROUP BY c.corporation_id;

MySQL select two columns multiple name value pair

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