sum of two columns in two tables mysql - mysql

i am developing a LMS system for an institute
and i am trying to develop a recovery report on the end of month
the report contains student name total fee package, total received, total receiveable, current month pending installment
here is the installment data of a student with his admission id
and this is the ledger data from where ican pick the fee package and total receiveable fees
and i am using this query for recovery report
SELECT
SUM(l.dr)-SUM(l.cr) as sum_remaining,
f.dr as fee_package,
SUM(i.payment) as this_month_install,
a.reg_id, s.fname
FROM
ledger l, ledger f, student_data s,
admissions a LEFT OUTER JOIN installments i ON a.admissionid = i.admissionid
WHERE
a.admissionid = '58ac4b5421488' AND
a.reg_id = s.reg_id AND
l.reference = '58ac4b5421488' AND
l.details <> 'registration fee' AND
f.reference = '58ac4b5421488' AND
f.details = 'Fee Package' AND
i.install_no <> '1' AND
MONTH(i.pay_date) = '04' AND
YEAR(i.pay_date) = '2017'
GROUP BY a.admissionid
and its giving the result like this
but the result should be like
sum_remaining = 10000
and this_month_install = 10000
please help me to sort out this problem
Thanks in advance

you should start from admission and use inner join for the others table (left join for installments)
SELECT
SUM(l.dr)-SUM(l.cr) as sum_remaining,
f.dr as fee_package,
SUM(i.payment) as this_month_install,
a.reg_id,
s.fname
FROM admissions a
Inner JOIN ledger f ON f.reference = a.admissionid AND f.details = 'Fee Package'
INNER JOIN ledger l ON l.reference = a.admissionid AND l.details <> 'registration fee'
INNER JOIN student_data s ON a.reg_id = s.reg_id
LEFT JOIN installments i ON a.admissionid = i.admissionid AND i.install_no <> '1'
WHERE a.admissionid = '58ac4b5421488'
AND MONTH(i.pay_date) = '04'
AND YEAR(i.pay_date) = '2017'
GROUP BY a.admissionid
you have two row in installments table that match .. try filter just one
SELECT
SUM(l.dr)-SUM(l.cr) as sum_remaining,
f.dr as fee_package,
SUM(i.payment) as this_month_install,
a.reg_id,
s.fname
FROM admissions a
Inner JOIN ledger f ON f.reference = a.admissionid AND f.details = 'Fee Package'
INNER JOIN ledger l ON l.reference = a.admissionid AND l.details <> 'registration fee'
INNER JOIN student_data s ON a.reg_id = s.reg_id
LEFT JOIN installments i ON a.admissionid = i.admissionid
AND i.install_no not in ( '1', '2')
WHERE a.admissionid = '58ac4b5421488'
AND MONTH(i.pay_date) = '04'
AND YEAR(i.pay_date) = '2017'
GROUP BY a.admissionid

i have done this with a sub query
thanks all
select a.admissionid, s.fname,
sum(l.dr)-SUM(l.cr) as sum_remaining, i.*,
f.dr as fee_package from student_data s,
ledger l, ledger f, admissions a
RIGHT outer join (select admissionid,
sum(payment) as this_month_install
from
installments g where g.install_no <> '1' and MONTH(g.pay_date) = '04' and YEAR(g.pay_date) = '2017' group by g.admissionid) i
ON
i.admissionid = a.admissionid where a.reg_id = s.reg_id and
a.status = 'studying' and a.course = 'PH' and
a.campus = 'CIFSD01' and l.reference = a.admissionid and
l.details <> 'registration fee' and f.reference = a.admissionid
and f.details = 'Fee Package' GROUP BY a.std_id

Related

Simplified SQL Query

Currently we have to run the following SQL Query to find all customers that have not been assigned access to a downloadable product.
SELECT c.entity_id as customer_id, dp.purchased_id as purchased_id
FROM magento_dev.sales_order as so
JOIN magento_dev.sales_order_address as soa on so.entity_id = soa.parent_id
JOIN magento_dev.customer_entity as c on c.email = soa.shipping_email
JOIN magento_dev.downloadable_link_purchased as dp on so.increment_id = dp.order_increment_id
where
so.customer_id = 12345 and
so.created_at > '2021-04-01' and
soa.shipping_email is not null and
dp.customer_id != c.entity_id
;
Which produces this:
customer_id purchased_id
99999 55555
Then with the results, we manually have to go through, and for each customer_id, and purchase_id run the following query:
UPDATE `magento_dev`.`downloadable_link_purchased` SET `customer_id` = '99999' WHERE (`purchased_id` = '55555');
So for the SQL Ninja's, any suggestions on how to make this a single query that finds the mismatched assignments and then does the update/insert at once?
Just put all the JOINs in the UPDATE query.
UPDATE `magento_dev`.`downloadable_link_purchased` AS dp1
JOIN magento_dev.sales_order as so
JOIN magento_dev.sales_order_address as soa on so.entity_id = soa.parent_id
JOIN magento_dev.customer_entity as c on c.email = soa.shipping_email
JOIN magento_dev.downloadable_link_purchased as dp
ON so.increment_id = dp.order_increment_id
AND dp.customer_id != c.entity_id
AND dp1.purchased_id = dp.purchased_id
SET dp1.customer_id = c.entity_id
where
so.customer_id = 12345 and
so.created_at > '2021-04-01' and
soa.shipping_email is not null
Can be done like sub query and join with the table which should be updated,
UPDATE
magento_dev.downloadable_link_purchased F
JOIN
(SELECT c.entity_id as customer_id, dp.purchased_id as purchased_id
FROM magento_dev.sales_order as so
JOIN magento_dev.sales_order_address as soa on so.entity_id = soa.parent_id
JOIN magento_dev.customer_entity as c on c.email = soa.shipping_email
JOIN magento_dev.downloadable_link_purchased as dp on so.increment_id = dp.order_increment_id
WHERE
so.customer_id = 12345 and
so.created_at > '2021-04-01' and
soa.shipping_email is not null and
dp.customer_id != c.entity_id) S
ON F.purchased_id = S.purchased_id
SET F.customer_id = S.customer_id;

invoice type fetch query from tables

ER diagram
ER diagram is attached
I need to get sales invoice invoices.type = 'sales' and invoices.type = 'purchase'
with company name as you can see in select statement
also sales and purchase columns
My query
SELECT jobs.id as jobID,
-- c.name AS Customer,jobs.job_no,
invoices.invoice_due_date,
jobs.id,
( (invoice_items.amount * invoice_items.quantity * invoice_items.exchange_rate )) as Ammount
FROM invoices
INNER JOIN `invoice_items` ON invoices.id = invoice_items.invoice_id
INNER JOIN `jobs` ON jobs.id = invoices.job_id
-- INNER JOIN `company` as c ON c.company_id = jobs.company_id -- jobs and company.
WHERE invoices.type = 'sales'
-- new conditions
AND MONTH(jobs.created_at) = '3'
AND YEAR(jobs.created_at) = '2017'
AND jobs.status > 0
AND jobs.complete_job > 0
AND jobs.completed_at IS NOT NULL
AND invoice_items.deleted_at IS NULL
GROUP BY jobs.job_no
ORDER BY invoices.invoice_due_date DESC
Try this updated...
SELECT jobs.id as jobID,
C.name AS Customer,jobs.job_no,
invoices.invoice_due_date,
jobs.id,
( (invoice_items.amount * invoice_items.quantity *invoice_items.exchange_rate )) as Ammount,
CASE invoices.type
WHEN 'sales' THEN 'S'
ELSE 'P'
END as trans_type
FROM invoices
INNER JOIN `invoice_items` ON invoices.id = invoice_items.invoice_id
INNER JOIN `jobs` ON jobs.id = invoices.job_id
LEFT OUTER JOIN `company` as C ON C.company_id = jobs.company_id
WHERE (invoices.type = 'sales' OR invoices.type = 'purchase') AND (MONTH(jobs.created_at) = '3') AND (YEAR(jobs.created_at) = '2017') AND (jobs.status > 0) AND (jobs.complete_job > 0) AND (jobs.completed_at IS NOT NULL)

Joining 2 SQL queries into 1 result

I have two SQL queries that I would like to join into one:
select d.full_month, COUNT(*) amount
from fact_ticket t
join dim_queue q on t.queue_id = q.queue_id
join vt_scopes s on t.scope_id = s.scope_id
join dim_date d on t.create_date_id = d.date_id
where q.name = 'Support'
and year(GETDATE()) = YEAR(t.create_date)
and s.statusname not in ('discarded', 'closed')
group by d.full_month
order by 1;
and
select d.full_month, COUNT(*) amount
from fact_ticket t
join dim_queue q on t.queue_id = q.queue_id
join vt_scopes s on t.scope_id = s.scope_id
join dim_date d on t.create_date_id = d.date_id
where q.name = 'Support'
and year(GETDATE()) = YEAR(t.create_date)
and s.statusname in ('closed')
group by d.full_month
order by 1;
Both gives me now a result with a date column and an amount column, but I would like to get everything in one query where I would get date, amount 1, amount 2.
Is there an easy to do this?
You can use below query-
SELECT d.full_month,
COUNT(IF(s.statusname NOT IN ('discarded', 'closed'),1,NULL)) amount1,
COUNT(IF(s.statusname IN ('closed'),1,NULL)) amount2
FROM fact_ticket t
JOIN dim_queue q ON t.queue_id = q.queue_id
JOIN vt_scopes s ON t.scope_id = s.scope_id
JOIN dim_date d ON t.create_date_id = d.date_id
WHERE q.name = 'Support'
AND YEAR(GETDATE()) = YEAR(t.create_date)
GROUP BY d.full_month
ORDER BY 1;
2nd Edition: Even you can get benefit of index if exist on create_date by below query-
SELECT d.full_month,
COUNT(IF(s.statusname NOT IN ('discarded', 'closed'),1,NULL)) amount1,
COUNT(IF(s.statusname IN ('closed'),1,NULL)) amount2
FROM fact_ticket t
JOIN dim_queue q ON t.queue_id = q.queue_id
JOIN vt_scopes s ON t.scope_id = s.scope_id
JOIN dim_date d ON t.create_date_id = d.date_id
WHERE q.name = 'Support'
AND t.create_date>= DATE_FORMAT(NOW(),'%Y-01-01 00:00:00') AND t.create_date <= DATE_FORMAT(NOW(),'%Y-12-31 23:59:59');
GROUP BY d.full_month
ORDER BY 1;
Another way using sum function
SELECT
d.full_month,
SUM(s.statusname NOT IN ('discarded', 'closed')) amount,
SUM(s.statusname = 'closed') amount_closed
FROM
fact_ticket t
JOIN dim_queue q
ON t.queue_id = q.queue_id
JOIN vt_scopes s
ON t.scope_id = s.scope_id
JOIN dim_date d
ON t.create_date_id = d.date_id
WHERE q.name = 'Support'
AND YEAR(GETDATE ()) = YEAR(t.create_date)
GROUP BY d.full_month
ORDER BY 1 ;

Only getting one result from sub select in inner join in mysql

Hi I have run into a dilemma, I am doing this query:
SELECT GROUP_CONCAT(DISTINCT(ca.category_name) SEPARATOR ', ') AS categories, pr.promo_name, pr.add_value_text, c.contract_id, c.cmeal_plan, c.cmin_markup, c.civa, c.tax_include, c.hotel_id, hi.hname, hi.hstars, im.image_file, pl.plan_name, ra.price
FROM contracts AS c
INNER JOIN hotel_info AS hi ON hi.hotel_id = c.hotel_id AND hi.destination_id = '6460'
INNER JOIN images AS im ON im.foreign_id = hi.hotel_id
INNER JOIN meal_plan AS pl ON pl.plan_code = c.cmeal_plan AND pl.lang = '1'
INNER JOIN hotel_categories AS hc ON hc.hotel_id = hi.hotel_id
INNER JOIN categories AS ca ON ca.category_code = hc.category_code AND ca.lang = '1'
LEFT JOIN
(SELECT
r.hotel_id, AVG(r.double) AS price
FROM
rates AS r ) AS ra
ON ra.hotel_id = hi.hotel_id
LEFT JOIN promotions AS pr ON pr.hotel_id = hi.hotel_id AND FIND_IN_SET(c.contract_id, pr.contract_id) > 0 AND pr.book_start <= '2012-11-01' AND pr.book_end >= '2012-11-02' AND travel_start <= '2012-11-23' AND travel_end >= '2012-11-30' AND pr.lang = '1'
WHERE c.cstart <= '2012-11-01' AND c.cend >= '2012-11-01'
AND hi.status = '1'
AND im.type ='1'
GROUP BY hi.hotel_id
I am getting all the desired results except for the sub select query.. each hotel has a price but it is only giving me back one result and the rest are all null. Is there an error in my query? If any additional information is needed please let me know and thank you in advance for any help!
You are missing the GROUP BY in your subquery, so MySQL will only return one-value. If you want all hotel_id's then you need to GROUP BY that field:
SELECT GROUP_CONCAT(DISTINCT(ca.category_name) SEPARATOR ', ') AS categories,
pr.promo_name,
pr.add_value_text,
c.contract_id,
c.cmeal_plan,
c.cmin_markup,
c.civa,
c.tax_include,
c.hotel_id,
hi.hname,
hi.hstars,
im.image_file,
pl.plan_name,
ra.price
FROM contracts AS c
INNER JOIN hotel_info AS hi
ON hi.hotel_id = c.hotel_id
AND hi.destination_id = '6460'
INNER JOIN images AS im
ON im.foreign_id = hi.hotel_id
INNER JOIN meal_plan AS pl
ON pl.plan_code = c.cmeal_plan
AND pl.lang = '1'
INNER JOIN hotel_categories AS hc
ON hc.hotel_id = hi.hotel_id
INNER JOIN categories AS ca
ON ca.category_code = hc.category_code
AND ca.lang = '1'
LEFT JOIN
(
SELECT r.hotel_id, AVG(r.double) AS price
FROM rates AS r
GROUP BY r.hotel_id <-- add a GROUP BY hotel_id then you will get avg() for each hotel
) AS ra
ON ra.hotel_id = hi.hotel_id
LEFT JOIN promotions AS pr
ON pr.hotel_id = hi.hotel_id
AND FIND_IN_SET(c.contract_id, pr.contract_id) > 0
AND pr.book_start <= '2012-11-01'
AND pr.book_end >= '2012-11-02'
AND travel_start <= '2012-11-23'
AND travel_end >= '2012-11-30'
AND pr.lang = '1'
WHERE c.cstart <= '2012-11-01'
AND c.cend >= '2012-11-01'
AND hi.status = '1'
AND im.type ='1'
GROUP BY hi.hotel_id

How can I make more than one select queries in single select query.

I have to write a query where, I need to fetch records for last week, last month, and for all.
For this problem I wrote 3 diffrent queries (for last week, for last month and for all)
For Weekly Info :-
SELECT bu.brand_name AS 'Brand_Name',COUNT(s.unique) AS '# Item Sold',SUM(s.price) AS 'Total_Price'
FROM item_details s
LEFT JOIN sales_order o ON s.fk_sales_order = o.id_sales_order
LEFT JOIN customer_info AS c ON o.fk_customer_id = c.id_customer
LEFT JOIN simple_details cc ON s.unique = cc.unique
LEFT JOIN config_details cf ON cc.fk_config_id = cf.config_id
LEFT JOIN brand_details cb ON cf.fk_brand_id = cb.brand_id
LEFT JOIN category_details ctc ON cf.fk_category_id = ctc.category_id
LEFT JOIN gender_details g ON cf.fk_gender_id = g.gender_id
LEFT JOIN buyers AS bu ON bu.brand_name = cb.name AND bu.category_name = ctc.name AND bu.gender = g.name
WHERE bu.buyers = 'xyz' AND DATE_FORMAT(o.created_date,'%Y-%m-%d') >= #weekstartdate AND DATE_FORMAT(o.created_date,'%Y-%m-%d') <= #weekenddate
GROUP BY bu.brand_name
For Monthly Info :-
SELECT bu.brand_name AS 'Brand_Name',COUNT(s.unique) AS '# Item Sold',SUM(s.price) AS 'Total_Price'
FROM item_details s
LEFT JOIN sales_order o ON s.fk_sales_order = o.id_sales_order
LEFT JOIN customer_info AS c ON o.fk_customer_id = c.id_customer
LEFT JOIN simple_details cc ON s.unique = cc.unique
LEFT JOIN config_details cf ON cc.fk_config_id = cf.config_id
LEFT JOIN brand_details cb ON cf.fk_brand_id = cb.brand_id
LEFT JOIN category_details ctc ON cf.fk_category_id = ctc.category_id
LEFT JOIN gender_details g ON cf.fk_gender_id = g.gender_id
LEFT JOIN buyers AS bu ON bu.brand_name = cb.name AND bu.category_name = ctc.name AND bu.gender = g.name
WHERE bu.buyers = 'xyz' AND DATE_FORMAT(o.created_date,'%Y-%m-%d') >= #monthstartdate AND DATE_FORMAT(o.created_date,'%Y-%m-%d') <= #monthenddate
GROUP BY bu.brand_name
For All Records :-
SELECT bu.brand_name AS 'Brand_Name',COUNT(s.unique) AS '# Item Sold',SUM(s.price) AS 'Total_Price'
FROM item_details s
LEFT JOIN sales_order o ON s.fk_sales_order = o.id_sales_order
LEFT JOIN customer_info AS c ON o.fk_customer_id = c.id_customer
LEFT JOIN simple_details cc ON s.unique = cc.unique
LEFT JOIN config_details cf ON cc.fk_config_id = cf.config_id
LEFT JOIN brand_details cb ON cf.fk_brand_id = cb.brand_id
LEFT JOIN category_details ctc ON cf.fk_category_id = ctc.category_id
LEFT JOIN gender_details g ON cf.fk_gender_id = g.gender_id
LEFT JOIN buyers AS bu ON bu.brand_name = cb.name AND bu.category_name = ctc.name AND bu.gender = g.name
WHERE bu.buyers = 'xyz'
GROUP BY bu.brand_name
and these are working fine (giving currect output).
But problem is that, I have to merge these three queries in single one.
Where output should be as
Brand name, item_sold(week), total_price(week),item_sold(month), total_price(month),item_sold(all), total_price(all)
How can I write this query?
Without looking deep into your code, the obvious solution would be
SELECT
all.brand_name
pw.items_sold items_sold_week
pw.total_price total_price_week
pm.items_sold items_sold_month
pm.total_price total_price_month
all.items_sold items_sold_all
all.total_price total_price_all
FROM
(your all-time select) all
JOIN (your per-month select) pm ON all.brand_name = pm.brand_name
JOIN (your per-week select) pw ON all.brand_name = pw.brand_name
Though you probably should rethink your entire approach and make sure whether you really want that kind of logic in a DB layer or it is better to be in your application.
You could use case to limit aggregates to a subset of rows:
select bu.brand_name
, count(case when date_format(o.created_date,'%Y-%m-%d') >= #weekstartdate
and date_format(o.created_date,'%Y-%m-%d') <= #weekenddate
then 1 end) as '# Item Sold Week'
, sum(case when date_format(o.created_date,'%Y-%m-%d') >= #weekstartdate
and date_format(o.created_date,'%Y-%m-%d') <= #weekenddate
then s.price end) as 'Total_Price Week'
, count(case when date_format(o.created_date,'%Y-%m-%d') >= #monthstartdate
and date_format(o.created_date,'%Y-%m-%d') <= #monthstartdate
then 1 end) as '# Item Sold Month'
, ...
If all three selects uses the same fields in the results, you can UNION them:
SELECT *
FROM (SELECT 1) AS a
UNION (SELECT 2) AS b
UNION (SELECT 3) AS c
If you need to tell week/mon/all records from each other - just add constant field containing "week" or "mon"
You cam use the UNION.keyword between the queries to bundle them.together BUT tje column types and sequence must be the same in all queries. You could add an identifier to each set