Please find the SQLfiddle URL:
http://sqlfiddle.com/#!2/c8002/1/0
Actual Output should be:
region_id status1 branches balance fses
status0 discount branch_names telecallers
2 NULL 4 400.00 30 KOTTAKKAL 341.00 3 3
2 NULL 4 800.00 31 KALPETTA 394.00 3 3
I'm getting the repeated output as follows:
region_id status1 branches balance fses
status0 discount branch_names telecallers
2 NULL 4 400.00 30 KOTTAKKAL 341.00 3 3
2 NULL 4 400.00 30 KOTTAKKAL 394.00 3 3
2 NULL 4 800.00 31 KALPETTA 341.00 3 3
2 NULL 4 800.00 31 KALPETTA 394.00 3 3
how do I correct the same?
Thanks & Regards,
Manjesh.
I guess you're having a problem in your query structure itself, as it's not simply a request for distinct.
Your joining tables, and retrieving distinct values for each row you have, that you actually wanted to be only one for each of KOTTAKKAL and KALPETTA.
Notice in your example that, although the addition of the clause distinct is performed, no difference will come over, as the rows you have are distinct. In column balance you have both 341.00 and 394.00 for each entry of KOTTAKKAL and KALPETTA.
If using group, yes, you will lose information on balance, as the result return after a group by is only the first of the different elements grouped (in case of a column with multiple values).
You either have to determine what result you want, or cope with having sum other calculation over the column balance.
I guess the result, and the proper join you were willing to do is this:
SELECT DISTINCT E.`region_id`,a0.status0,a1.status1,k.discount,k.branches
,k.branch_names, k.balance,TCLRS.telecallers,FSE.fses
FROM tbl_insurance_excel E
LEFT OUTER JOIN (SELECT E2.region_id, count(`id`) AS status1
FROM tbl_insurance_excel E2 LEFT JOIN tbl_recipt_general_details ON id=insurance_excel_id
JOIN tbl_branches ON policy_closed_branch= branch_id
WHERE E2.`row_status` =1 AND E2.canceled_status='no' AND E2.region_id=2 GROUP BY region_id) a1 ON a1.region_id=E.region_id
LEFT OUTER JOIN (SELECT E2.region_id, count(`id`) AS status0
FROM tbl_insurance_excel E2 LEFT JOIN tbl_recipt_general_details ON id=insurance_excel_id
JOIN tbl_branches ON policy_closed_branch= branch_id
WHERE E2.`row_status` =0 AND E2.canceled_status='no' AND E2.region_id=2 GROUP BY region_id) a0 ON a0.region_id=E.region_id
LEFT JOIN (
SELECT IEX.region_id, B.branch_name AS branch_names, B.branch_id AS branches, sum( DDT.discounts_amount ) AS discount, sum( RGD.`recipt_bal_amount` ) AS balance
FROM tbl_insurance_excel IEX
LEFT JOIN tbl_recipt_general_details RGD ON IEX.id = RGD.insurance_excel_id
LEFT JOIN tbl_discounts_details DDT ON RGD.rec_gene_id = DDT.recipt_general_id
LEFT JOIN tbl_branches B ON B.branch_id = RGD.policy_closed_branch
WHERE IEX.region_id =2
GROUP BY B.branch_id)k ON k.region_id=E.region_id
LEFT JOIN (
SELECT ex.region_id, B.branch_id AS branches, count( F.`fse_id` ) AS telecallers
FROM tbl_branches B
LEFT JOIN tbl_team_leader L ON B.branch_id = L.leader_branch_id
LEFT JOIN tbl_fse F ON L.leader_id = F.leader_id
JOIN (
SELECT region_id
FROM tbl_insurance_excel
WHERE `region_id` =2
GROUP BY region_id
) AS ex ON B.region_id = ex.region_id
WHERE F.fse_category = 'Telecaller'
GROUP BY B.branch_id
) TCLRS ON TCLRS .region_id=E.region_id
LEFT JOIN (
SELECT ex.region_id, B.branch_id AS branches, count( F.`fse_id` ) AS fses
FROM tbl_branches B
LEFT JOIN tbl_team_leader L ON B.branch_id = L.leader_branch_id
LEFT JOIN tbl_fse F ON L.leader_id = F.leader_id
JOIN (
SELECT region_id
FROM tbl_insurance_excel
WHERE `region_id` =2
GROUP BY region_id
) AS ex ON B.region_id = ex.region_id
WHERE F.fse_category = 'Fse'
GROUP BY B.branch_id
) FSE ON FSE.region_id=E.region_id
WHERE E.region_id=2 GROUP BY k.branches
Notice you were doing a join after the other, and combining results that should be unique in your query. You'd joined the data from the query you named k, and then joined the result with the query you named BAL, that, except by the column balance, had the same entries, and so the branch_id's were being duplicated.
You had, in a quick:
k.branch_id LEFT JOIN BAL.branch_id
which caused your rows to be duplicated, with different balance values.
The result obtained with the query posted is:
REGION_ID STATUS0 STATUS1 DISCOUNT BRANCHES BRANCH_NAMES BALANCE TELECALLERS FSES
2 (null) 4 400 30 KOTTAKKAL 341 3 3
2 (null) 4 800 31 KALPETTA 394 3 3
Regards!
Try This ::
IN your query just append the following part :
GROUP BY branch_names
OR you can get the DISTINCT in your SELECT part as :
Select DISTINCT(branch_names) from....
The final query will be ::
SELECT E.`region_id`,a0.status0,a1.status1,k.discount,k.branches
,k.branch_names,BAL.balance,TCLRS.telecallers,FSE.fses
FROM tbl_insurance_excel E
LEFT OUTER JOIN (Select E2.region_id, count(`id`) as status1
from tbl_insurance_excel E2 Left Join tbl_recipt_general_details on id=insurance_excel_id
JOIN tbl_branches on policy_closed_branch= branch_id
Where E2.`row_status` =1 AND E2.canceled_status='no' and E2.region_id=2 Group by region_id) a1 ON a1.region_id=E.region_id
LEFT OUTER JOIN (Select E2.region_id, count(`id`) as status0
from tbl_insurance_excel E2 Left Join tbl_recipt_general_details on id=insurance_excel_id
JOIN tbl_branches on policy_closed_branch= branch_id
Where E2.`row_status` =0 AND E2.canceled_status='no' and E2.region_id=2 Group by region_id) a0 ON a0.region_id=E.region_id
LEFT JOIN (
SELECT IEX.region_id,B.branch_name as branch_names,B.branch_id as branches, sum( DDT.discounts_amount ) as discount
FROM tbl_insurance_excel IEX
LEFT JOIN tbl_recipt_general_details RGD ON IEX.id = RGD.insurance_excel_id
LEFT JOIN tbl_discounts_details DDT ON RGD.rec_gene_id = DDT.recipt_general_id
LEFT JOIN tbl_branches B ON B.branch_id = RGD.policy_closed_branch
WHERE IEX.region_id =2
GROUP BY B.branch_id)k on k.region_id=E.region_id
LEFT JOIN (
SELECT IEX.region_id,B.branch_id as branches, sum( RGD.`recipt_bal_amount` ) AS balance
FROM tbl_insurance_excel IEX
LEFT JOIN tbl_recipt_general_details RGD ON IEX.id = RGD.insurance_excel_id
LEFT JOIN tbl_branches B ON B.branch_id = RGD.policy_closed_branch
WHERE IEX.region_id =2
GROUP BY B.branch_id)BAL ON BAL.region_id=E.region_id
LEFT JOIN (
SELECT ex.region_id, B.branch_id AS branches, count( F.`fse_id` ) AS telecallers
FROM tbl_branches B
LEFT JOIN tbl_team_leader L ON B.branch_id = L.leader_branch_id
LEFT JOIN tbl_fse F ON L.leader_id = F.leader_id
JOIN (
SELECT region_id
FROM tbl_insurance_excel
WHERE `region_id` =2
GROUP BY region_id
) AS ex ON B.region_id = ex.region_id
WHERE F.fse_category = 'Telecaller'
GROUP BY B.branch_id
) TCLRS ON TCLRS .region_id=E.region_id
LEFT JOIN (
SELECT ex.region_id, B.branch_id AS branches, count( F.`fse_id` ) AS fses
FROM tbl_branches B
LEFT JOIN tbl_team_leader L ON B.branch_id = L.leader_branch_id
LEFT JOIN tbl_fse F ON L.leader_id = F.leader_id
JOIN (
SELECT region_id
FROM tbl_insurance_excel
WHERE `region_id` =2
GROUP BY region_id
) AS ex ON B.region_id = ex.region_id
WHERE F.fse_category = 'Fse'
GROUP BY B.branch_id
) FSE ON FSE.region_id=E.region_id
where E.region_id=2 group by k.branches
did u try to wrap your query with another select and group it by BRANCH_NAMES
SELECT * FROM
(
<< your query goes here>>
) o
GROUP BY o.BRANCH_NAMES
But in case u put your results together like this, you will defnitely loose data in balance column.
Related
I need the sum of two customers each so I wrote the following query:
SELECT m.m_name, m2.m_name AS m_name2, SUM(m.price + m2.price) as total_amount, rn.name
FROM
(
SELECT m.name AS m_name, m.id AS m_id ,IFNULL(SUM(d.num * p.price), 0) AS price
FROM m_member as m
LEFT JOIN t_sales AS t ON m.id = t.m_id
INNER JOIN m_product as p
LEFT JOIN t_sales_detail as d ON t.id = d.id AND p.id = d.p_id
GROUP BY m.id
)AS m
LEFT JOIN
(
SELECT m.name AS m_name, m.id AS m2_id ,IFNULL(SUM(d.num * p.price), 0) AS price
FROM m_member as m
LEFT JOIN t_sales AS t ON m.id = t.m_id
INNER JOIN m_product as p
LEFT JOIN t_sales_detail as d ON t.id = d.id AND p.id = d.p_id
GROUP BY m.id
) AS m2 ON m.m_id != m2.m2_id
JOIN m_lank AS rn ON (SELECT SUM(m.price + m2.price)) BETWEEN rn.low_limit AND rn.up_limit
GROUP BY m.m_id, m2.m2_id
order by total_amount;
The results looks like this:
# m_name m_name2 total_amount name
Nagayama Kawata 380 Bronze
Kawata Nagayama 380 Bronze
Nagaoku Kawata 500 Bronze
Kawata Nagaoku 500 Bronze
Nagayama Nagaoku 880 Bronze
Nagaoku Nagayama 880 Bronze
Kawashima Kawata 2620 Bronze
Kawata Kawashima 2620 Bronze
...
The problem is, I don't need to sum the same customer two times.
How can I get rid of the duplicate results? Anyone has a solution?
EDIT:
I want something like this:
# m_name m_name2 total_amount name
Nagayama Kawata 380 Bronze
Nagaoku Kawata 500 Bronze
Nagayama Nagaoku 880 Bronze
Kawashima Kawata 2620 Bronze
...
Sorry for my poor English. It might be difficult to understand what I need.
Basically I have in total five customers.
Customer A has bought a total of 400$
Customer B has bought a total of 1030$.
Customer C .... 1540$.
Customer D .... 0$.
Customer F .... 320$.
Now I want to sum every customer with each other:
A + B
A + C
A + D
A + F
B + C
B + D
B + F
C + D
C + F
D + F
Using a CTE we get to reuse the table user_totals without a duplication:
WITH user_totals AS
(SELECT s.m_id AS id,
sum(sd.num*p.price) AS sales_amount
FROM t_sales_detail sd
JOIN m_product p ON sd.p_id=p.id
JOIN t_sales s ON s.id=sd.id
GROUP BY s.m_id)
SELECT m1.name,
m2.name,
t1.sales_amount+t2.sales_amount
FROM user_totals t1
JOIN user_totals t2 ON t1.id < t2.id
JOIN m_member m1 ON t1.id = m1.id
JOIN m_member m2 ON t2.id = m2.id
Like the other answer greater than/less than is a good JOIN criteria for getting only one match.
!= makes a bad join criteria as you're after a non-match on all rows, it rarely does what you expect.
An illustration of this is fiddle
Note: row limits and IFNULL criteria removed for readabilit
If I understood you correctly, it can be achieved with the minimal change to your query. Just replace != with < or >. Thus you will get each pair only once.
SELECT m.m_name, m2.m_name AS m_name2, SUM(m.price + m2.price) as total_amount, rn.name
FROM
(
SELECT m.name AS m_name, m.id AS m_id ,IFNULL(SUM(d.num * p.price), 0) AS price
FROM m_member as m
LEFT JOIN t_sales AS t ON m.id = t.m_id
INNER JOIN m_product as p
LEFT JOIN t_sales_detail as d ON t.id = d.id AND p.id = d.p_id
GROUP BY m.id
)AS m
LEFT JOIN
(
SELECT m.name AS m_name, m.id AS m2_id ,IFNULL(SUM(d.num * p.price), 0) AS price
FROM m_member as m
LEFT JOIN t_sales AS t ON m.id = t.m_id
INNER JOIN m_product as p
LEFT JOIN t_sales_detail as d ON t.id = d.id AND p.id = d.p_id
GROUP BY m.id
) AS m2 ON m.m_id > m2.m2_id
JOIN m_lank AS rn ON (SELECT SUM(m.price + m2.price)) BETWEEN rn.low_limit AND rn.up_limit
GROUP BY m.m_id, m2.m2_id
order by total_amount;
i have queries like this
SET #curr_date = '2017-03-23';
SELECT
curr_week.mid AS MID,
curr_week.EDC AS Merchant_Name ,
COALESCE(curr_week.amount,0) AS Total_Amount_Curr_Week,
COALESCE(curr_week.total_trx,0) AS Total_Trx_Curr_Week,
COALESCE(curr_week.total_user,0) AS Total_User_Curr_Week,
COALESCE(last_week.amount,0) AS Total_Amount_Last_Week,
COALESCE(last_week.total_trx,0) AS Total_Trx_Last_Week,
COALESCE(last_week.total_user,0) AS Total_User_Last_Week
FROM
(
SELECT a.*, b.total_user
FROM
(
SELECT a1.owner_name AS MID, m.name AS EDC,SUM(t1.amount) AS amount, COUNT(t1.id) AS total_trx
FROM members m
JOIN accounts a1 ON a1.member_id = m.id
JOIN transfers t1 ON a1.id = t1.to_account_id
WHERE DATE(t1.DATE) = (#curr_date - INTERVAL 1 DAY)
GROUP BY a1.owner_name
) AS a
JOIN
(-- get total user
SELECT COUNT(r.ecash_no) AS total_user, r.mid, r.merchant_name
FROM
(
SELECT a.`owner_name` AS ecash_no,
a1.owner_name AS MID,
m.name AS merchant_name
FROM accounts a1
JOIN transfers t1 ON a1.id = t1.to_account_id
JOIN members m ON a1.member_id = m.id
JOIN accounts a ON a.id = t1.from_account_id
WHERE DATE(t1.date) = (#curr_date - INTERVAL 1 DAY)
GROUP BY a.owner_name,m.`name`
) AS r
GROUP BY r.mid
) AS b ON a.mid = b.mid
) AS curr_week
JOIN
(
-- last week
SELECT a.*, b.total_user
FROM
(
SELECT a1.owner_name AS MID, m.name AS EDC,SUM(t1.amount) AS amount, COUNT(t1.id) AS total_trx
FROM members m
JOIN accounts a1 ON a1.member_id = m.id
JOIN transfers t1 ON a1.id = t1.to_account_id
WHERE DATE(t1.DATE) = (#curr_date - INTERVAL 1 DAY) - INTERVAL 1 WEEK
GROUP BY a1.owner_name
) AS a
JOIN
(-- get total user
SELECT COUNT(r.ecash_no) AS total_user, r.mid, r.merchant_name
FROM (
SELECT a.`owner_name` AS ecash_no,
a1.owner_name AS MID,
m.name AS merchant_name
FROM accounts a1
JOIN transfers t1 ON a1.id = t1.to_account_id
JOIN members m ON a1.member_id = m.id
JOIN accounts a ON a.id = t1.from_account_id
WHERE DATE(t1.date) = (#curr_date - INTERVAL 1 DAY) - INTERVAL 1 WEEK
GROUP BY a.owner_name,m.`name`
) AS r
GROUP BY r.mid
) AS b ON a.mid = b.mid
) AS last_week ON curr_week.mid = last_week.mid
how can i retrieve all EDC value from joined queries like that.
because if i use join , it displayed only the same values.
and if i use left join, it follows the value from the left query
is there any way to display everything with join?
You can simulate a full outer join of the two tables using the following:
SELECT COALESCE(a.ColA, b.ColA) AS ColA,
COALESCE(a.ColB, b.ColB) AS ColB
FROM tableA a
LEFT JOIN tableB b ON a.ColA = b.ColA
UNION
SELECT COALESCE(a.ColA, b.ColA) AS ColA,
COALESCE(a.ColB, b.ColB) AS ColB
FROM tableA a
RIGHT JOIN tableB b ON a.ColA = b.ColA;
Note: I've assumed that only ColA is the join column. You can add ColB as a join column as well, or use only ColB as a join column. This really depends on the design of your table, but the general approach I gave should still work.
Output:
Demo here:
Rextester
I have the following query which works (without the "WHERE stats.dt" part). I get all users with their data.
My problem is that this query of course results in rows ONLY with users that have stats.dt > $timestampnow-$maxdays_data). But I need ALL users but their values of SUM(upload) or SUM(download) need only to be fetched when stats.dt is larger than tstamp-maxdays. The other rows with values of upload and download where stats.dt is smaller than what I need, can be ignored.
An example would be that the user with nodeid 2 would not be selected because his dt is too small. I do want the user to be selected but just not with data or upload values (they can be 0).
The stats table looks like this
nodeid | dt | upload | download
----------------------------------------
1 | 1381699533 | 345345 | 42324234
1 | 1382899152 | 7575 | 574234
1 | 1380699533 | 764534 | 7235232
2 | 1372899152 | 71455 | 124123
I don't know where to start looking how to solve this so maybe somebody out there can point me in the right direction. Thanks!
SELECT b.id, b.lastname, b.name, c.balance, a.maxdebt, b.warndata, b.warndownload, b.warnupload, b.warndebt, b.cutoffdata, b.cutoffdownload, b.cutoffupload, b.cutoffdebt, b.data, b.download, b.upload, b.warning, b.access, b.cutoffstop
FROM (
SELECT customers.id AS id, SUM(tariffs.value) AS maxdebt
FROM tariffs
LEFT JOIN assignments ON tariffs.id = assignments.tariffid
RIGHT JOIN customers ON assignments.customerid = customers.id
GROUP BY id
) a
JOIN (
SELECT customers.id AS id, UPPER(lastname) AS lastname, customers.name AS name, SUM(stats.upload+stats.download) AS data, SUM(stats.download) AS download, SUM(stats.upload) AS upload, customers.cutoffstop, warndata, warndownload, warnupload, warndebt, cutoffdata, cutoffdownload, cutoffupload, cutoffdebt, nodes.warning, nodes.access
FROM customers
LEFT JOIN nodes ON customers.id = nodes.ownerid
LEFT JOIN stats ON nodes.id = stats.nodeid
LEFT JOIN customerwarnings ON customers.id = customerwarnings.id
WHERE stats.dt > ($timestampnow-$maxdays_data)
GROUP BY id
) b ON a.id = b.id
JOIN (
SELECT customerid, SUM(cash.value) AS balance
FROM cash
GROUP BY customerid
) c ON b.id = c.customerid
Here's a brute force way of doing it. It can almost certainly be simplified, but without knowing more about the table and foreign key structures it's hard to be sure.
What I've done is replace sum(stats.download) with sum(case when stats.dt > ($timestampnow-$maxdays_data) then s.download end) and similarly for upload. I've also changed the join on b to be an outer join:
Select
b.id,
b.lastname,
b.name,
c.balance,
a.maxdebt,
b.warndata,
b.warndownload,
b.warnupload,
b.warndebt,
b.cutoffdata,
b.cutoffdownload,
b.cutoffupload,
b.cutoffdebt,
b.data,
b.download,
b.upload,
b.warning,
b.access,
b.cutoffstop
From (
Select
c.id,
sum(t.value) as maxdebt
From
tariffs t
left join
assignments a
on t.id = a.tariffid
right join
customers
on a.customerid = c.id
Group by
c.id
) a left outer join (
Select
c.id,
upper(lastname) as lastname,
c.name,
sum(s.upload + s.download) as data,
sum(case when stats.dt > ($timestampnow-$maxdays_data) then s.download end) as download,
sum(case when stats.dt > ($timestampnow-$maxdays_data) then s.upload end) as upload,
c.cutoffstop,
warndata,
warndownload,
warnupload,
warndebt,
cutoffdata,
cutoffdownload,
cutoffupload,
cutoffdebt,
n.warning,
n.access
From
customers c
left join
nodes n
on c.id = n.ownerid
left join
stats s
on n.id = s.nodeid
left join
customerwarnings w
on c.id = w.id
Group By
c.id
) b
On a.id = b.id
inner join (
Select
customerid,
sum(cash.value) as balance
From
cash
Group By
customerid
) c
on a.id = c.customerid
Our db stores customer orders in two tables: customerorders and customerorderlines.
Amongst other fields, there is a customerorders.type field which determines (being = 1 or = 2)
if that customerorder is an invoice or a creditnote.
We currently have a report that lists amount of units sold, profits etc but with its current query, only displays total units sold over the period, ie, it doesnt subtract the number of credits, if any. Here is its sql and an example of the results it generates:
(apologies for the massive query that follows :))
SELECT l.name AS locationname
, sr.name AS salesrepname
, ct.name AS customertypename
, c.name AS customername
, c.id AS customer_id
, c.code
, s.name AS suppliername
, p.description AS productname
, p.id AS product_id
, p.unitofmeasure
, SUM(col.vatableprice) AS totalsales
, SUM(col.vatprice) AS vat
, SUM(col.quantity) AS totalitems
, SUM(col.quantity * col.costprice) AS totalsalecost
, SUM(col.vatableprice) - SUM(col.quantity * col.costprice) AS totalprofit
,(
SELECT SUM(col2.vatableprice) AS totalsales
FROM customerorders AS co2
LEFT JOIN customerorderlines AS col2 ON col2.customerorder_id = co2.id
LEFT JOIN customers AS c2 ON c2.id = co2.customer_id
LEFT JOIN locations AS l2 ON l2.id = c2.location_id
LEFT JOIN customertypes AS ct2 ON ct2.id = c2.customertype_id
LEFT JOIN salesreps AS sr2 ON sr2.id = c2.salesrep_id
LEFT JOIN products AS p2 ON p2.id = col2.product_id
LEFT JOIN suppliers AS s2 ON s2.id = p2.supplier_id
WHERE c.salesrep_id = c2.salesrep_id
AND co2.type = 2 AND p2.supplier_id = 179
AND co2.orderdate >= '2010-01-01 00:00:00'
AND co2.orderdate <= '2010-02-01 23:59:59'
) AS credits
,(
SELECT SUM(col2.vatprice) AS totalvat FROM customerorders AS co2
LEFT JOIN customerorderlines AS col2 ON col2.customerorder_id = co2.id
LEFT JOIN customers AS c2 ON c2.id = co2.customer_id
LEFT JOIN locations AS l2 ON l2.id = c2.location_id
LEFT JOIN customertypes AS ct2 ON ct2.id = c2.customertype_id
LEFT JOIN salesreps AS sr2 ON sr2.id = c2.salesrep_id
LEFT JOIN products AS p2 ON p2.id = col2.product_id
LEFT JOIN suppliers AS s2 ON s2.id = p2.supplier_id
WHERE c.salesrep_id = c2.salesrep_id
AND co2.type = 2
AND p2.supplier_id = 179
AND co2.orderdate >= '2010-01-01 00:00:00'
AND co2.orderdate <= '2010-02-01 23:59:59'
) AS creditsvat
FROM customerorders AS co
LEFT JOIN customerorderlines AS col ON col.customerorder_id = co.id
LEFT JOIN customers AS c ON c.id = co.customer_id
LEFT JOIN locations AS l ON l.id = c.location_id
LEFT JOIN customertypes AS ct ON ct.id = c.customertype_id
LEFT JOIN salesreps AS sr ON sr.id = c.salesrep_id
LEFT JOIN products AS p ON p.id = col.product_id
LEFT JOIN suppliers AS s ON s.id = p.supplier_id
WHERE co.status_v = 5
AND co.type = 1
AND p.supplier_id = 179
AND co.orderdate >= '2010-01-01 00:00:00' AND co.orderdate <= '2010-02-01 23:59:59'
GROUP BY c.salesrep_id
Which, in this case (grouping etc is determined by application code) generates a 'per sales rep' report:
Rep | TotalItems | SalesValue| CostOfSales | Profit | VAT | Credits | Credits(VAT)
Rep1| 937 | £5796.49 | £3606.49 | £2190.00 | £1013.73 | £220.12 | £38.57
Rep2| 1905 | £11695.09 | £7314.95 | £4380.14 | £2045.32 | £268.85 | £47.00
Rep3| 1074 | £6346.61 | £3950.53 | £2396.08 | £1109.76 | £54.89 | £9.57
Rep4| 2687 | £16129.42 | £10171.65 | £5957.77 | £2820.46 | £839.15 | £146.78
So, the problem lies in that TotalItems is the absolute number of items sold (all customerorders of type = 1). The credits field shows total cost of items in the period of type = 2, ie returned. TotalItems should have the qty of credits deducted from it so at a glance it can be seen what has actually been sold and of course all the other fields need their Credits counterpart deducting from each other too so that they reflect the correct amounts for items sold.
At first I thought this would be as simple modification to the existing query, but then noticed that i could not reference subquery aliases in the select so I rewrote the whole query using JOIN (SELECT ....) AS sales / JOIN (SELECT .....) AS credits so I could then reference sales.qty and credits.qty from the SELECT at the top of the query but then that didnt scale at all unless you were doing little queries.
This is how far I got:
(Yes, Im querying for different things here... this would be essentially the simplest form of the query: sales / credits for a single product)
SELECT sr.name AS salesrepsname
,l.name AS locationname
,sup.name AS suppliername
,p.description AS productname
,sales.qty AS sold
,credits.qty AS credits
,sales.qty - credits.qty AS actualsold
FROM
customerorders co
LEFT JOIN customerorderlines col ON col.customerorder_id = co.id
LEFT JOIN customers c ON c.id = co.customer_id
LEFT JOIN products p ON p.id = col.product_id
LEFT JOIN salesreps sr ON sr.id = c.salesrep_id
LEFT JOIN locations l ON l.id = c.location_id
LEFT JOIN suppliers sup ON sup.id = p.supplier_id
JOIN (SELECT SUM(col.quantity) AS qty,
SUM(col.vatableprice) AS total FROM customerorderlines col
LEFT JOIN customerorders co ON co.id = col.customerorder_id
WHERE col.product_id = 27642 AND co.type = 1)
AS sales
JOIN (SELECT SUM(col2.quantity) AS qty FROM customerorderlines col2
LEFT JOIN customerorders co2 ON co2.id = col2.customerorder_id
WHERE col2.product_id = 27642 AND co2.type = 2) AS credits
WHERE col.product_id = 27642
GROUP BY c.salesrep_id
So I have to admit Im a bit stuck, not being very knowledgable with mysql at all.
Any suggestions are very welcome and please feel free to point me towards any literature on advanced subquerying and joins that I should be reading.
Cheers!
I think the trick you may be looking for is along these lines. In any given query/subquery you want to fix, use some SQL like this, selecting all the rows, regardless of whether it's an invoice or a creditnote, and summing a value that's either positive or negative depending on which way the order/money is going:
SELECT
SUM(CASE WHEN co.type = 1 THEN col.quantity ELSE -col.quantity END)
FROM
...
Get it? You grab all your order lines back, but when you do the sum, you're adding up positive credits and negative debits, to get the real total in one operation.
I need some help performing my SELECTs. I made an SQL fiddle to show you the database.
I need to perform two queries but they didn't work fine:
First:
SELECT s.id, s.day_of_week, s.title
FROM slots s
LEFT JOIN bookings_has_slots bhs
ON s.id = bhs.slot_id
LEFT JOIN bookings b
ON bhs.booking_id = b.id
WHERE NOT EXISTS (
SELECT null
FROM bookings_has_slots bhs2
LEFT JOIN bookings b2
ON bhs2.booking_id = b2.id
WHERE b.date = '2018-01-27'
)
AND s.service_id = 3
AND s.day_of_week = DAYOFWEEK('2018-01-27');
Returns:
id day_of_week title
3 7 Après-midi (14h30 - 17h00)
But I expect:
no results, because the three slots possibilities for this day_of_week on the same date are taken.
Second:
SELECT DISTINCT b3.date AS unavailable_date
FROM bookings b3
LEFT JOIN bookings_has_slots bhs3
ON bhs3.booking_id = b3.id
LEFT JOIN slots s3
ON s3.id = bhs3.slot_id
WHERE NOT EXISTS (
SELECT null
FROM slots s
LEFT JOIN bookings_has_slots bhs
ON s.id = bhs.slot_id
LEFT JOIN bookings b
ON bhs.booking_id = b.id
WHERE NOT EXISTS (
SELECT null
FROM bookings_has_slots bhs2
LEFT JOIN bookings b2
ON bhs2.booking_id = b2.id
WHERE b.date = b2.date
)
AND s.service_id = 3
AND s.day_of_week = s3.day_of_week
);
Returns:
unavailable_date
2018-01-17
2018-01-31
2018-01-27
2018-02-03
But I expect:
unavailable_date
2018-01-17
2018-01-31
2018-01-27
Because here, there are two others slots available for the "2018-02-03" not taken by any other bookings.
Here is the sql fiddle :
http://sqlfiddle.com/#!9/89e46/9
Thanks for any help.
It is not the answer yet.
But Could you confirm that this will fix your 1st query:
SELECT s.id, s.day_of_week, s.title
FROM slots s
LEFT JOIN (
SELECT slot_id, booking_id
FROM bookings_has_slots bhs
INNER JOIN bookings b
ON b.id = bhs.booking_id
AND b.date = '2018-02-03'
) bhs
ON s.id = bhs.slot_id
WHERE s.day_of_week = DAYOFWEEK('2018-02-03')
AND bhs.booking_id IS NULL;
2nd query:
http://sqlfiddle.com/#!9/53a998/1
SELECT d.date unavailable_date, d.used_slots
FROM (
SELECT b.date, COUNT(b.id) used_slots
FROM bookings b
GROUP BY b.date
) d
LEFT JOIN slots s
ON s.day_of_week = DAYOFWEEK(d.date)
GROUP BY d.date
HAVING d.used_slots = COUNT(s.id);