MySQL Select problems - mysql

Table #1: qa_returns_items
Table #2: qa_returns_residues
I have a long time trying to get this Result:
item_code - item_quantity
2 - 1
3 - 2
IF qa_returns_items.item_code = qa_returns_residues.item_code AND status_code = 11 THEN
item_quantity = qa_returns_items.item_quantity -
qa_returns_residues.item_quantity
ELSEIF qa_returns_items.item_code = qa_returns_residues.item_code AND status_code = 12 THEN
item_quantity = qa_returns_items.item_quantity +
qa_returns_residues.item_quantity
ELSE
show diferendes
END IF
I tried this Query:
select SubQueryAlias.item_code,
item_quantity
from (
select
ri.item_code
, case status_code
when 11 then ri.item_quantity - rr.item_quantity
when 12 then ri.item_quantity + rr.item_quantity
end as item_quantity
from qa_returns_residues rr
left join qa_returns_items ri
on ri.item_code = rr.item_code
WHERE ri.returnlog_code = 1
) as SubQueryAlias
where item_quantity > 0 GROUP BY (item_code);
The query returns this result:
item_code - item_quantity
1 - 2
2 - 2

Try this query. I havn't tested it. It is very difficult what you require. But I have built it from table structure and given condition clause.
select qa_returns_items.item_code,
(CASE status_code
WHEN 11 THEN (qa_returns_items.item_quantity - qa_returns_residues.item_quantity)
WHEN 12 THEN (qa_returns_items.item_quantity + qa_returns_residues.item_quantity) END) as item_quantity ,
qa_returns_residues.item_unitprice,
( qa_returns_residues.item_unitprice * item_quant) as item_subtotal,
(qa_returns_residues.item_discount * item_quantity) as item_discount,
( ( qa_returns_residues.item_unitprice * item_quant) -
(qa_returns_residues.item_discount * item_quantity) ) as item_total
where
item_quantity > 0 AND qa_returns_items.item_code = qa_returns_residues.item_code
Update:
select qa_returns_items.item_code,
(CASE status_code
WHEN 11 THEN (qa_returns_items.item_quantity - qa_returns_residues.item_quantity)
WHEN 12 THEN (qa_returns_items.item_quantity + qa_returns_residues.item_quantity) END) as item_quant ,
qa_returns_residues.item_unitprice,
( qa_returns_residues.item_unitprice * item_quant) as item_subtotal,
(qa_returns_residues.item_discount * item_quantity) as item_discount,
( ( qa_returns_residues.item_unitprice * item_quant) -
(qa_returns_residues.item_discount * item_quantity) ) as item_total
where
(CASE status_code
WHEN 11 THEN (qa_returns_items.item_quantity - qa_returns_residues.item_quantity)
WHEN 12 THEN (qa_returns_items.item_quantity + qa_returns_residues.item_quantity) END) item_quant > 0 AND qa_returns_items.item_code = qa_returns_residues.item_code

In my experience I would advice you to start over with a fresh database, no records and start debugging step by step.
First create the database and the tables. After that insert only 2 records with simple data. Afterwards start debugging.
From what I was able to debug the problem is in your sub-select. In the topic you want to see item_code 2 and 3. That can't happen because:
SELECT ri.item_code,
CASE status_code
WHEN 11 then ri.item_quantity - rr.item_quantity
WHEN 12 then ri.item_quantity + rr.item_quantity
END AS item_quantity
FROM qa_returns_residues rr
LEFT JOIN qa_returns_items ri
ON ri.item_code = rr.item_code
WHERE ri.returnlog_code = 1 // Why do you need this for ?
returns
item_code item_quantity
2 2
1 0
1 0
1 0
1 2
And then the main query selects only the results which have item_quantity > 0.
Thus you get only
item_code item_quantity
1 2
2 2
as a result.
I'm not quite sure what's the purpose of this operation but have in mind that simple solutions are always best!

I solved my problem:
SELECT
item_code,
item_quantity,
item_unitprice,
item_subtotal,
item_discount,
item_total
FROM (
SELECT qa_returns_items.item_code,
qa_returns_items.item_quantity,
qa_returns_items.item_unitprice,
qa_returns_items.item_subtotal,
qa_returns_items.item_discount,
qa_returns_items.item_total
FROM qa_returns_items
WHERE returnlog_code = 1
UNION
SELECT qa_returns_residues.item_code,
qa_returns_residues.item_quantity,
qa_returns_residues.item_unitprice,
qa_returns_residues.item_subtotal,
qa_returns_residues.item_discount,
qa_returns_residues.item_total
FROM qa_returns_residues
WHERE returnlog_code = 1
ORDER BY item_code ASC
)
AS SubQueryAlias
WHERE item_code NOT IN (
SELECT a.item_code
FROM qa_returns_items a
JOIN qa_returns_residues b
ON b.item_code = a.item_code
WHERE a.returnlog_code = 1
AND b.returnlog_code = 1
);

Related

Redshift Correlated Subquery error internal

I have a query in MYSQL which count products from specific vendor with product_status like Live, Pause, soldout, Partial-Soldout etc. Query include Subquery but works perfect in Mysql. For Redshift (Postgre v8.x) it gives error correlated subquery pattern is not supported due to internal error
Query (POSTGRES)
SELECT COUNT(CASE WHEN (vendor_id = 6 AND status = 1) THEN 1 ELSE NULL END) AS "vex",
COUNT(CASE WHEN (vendor_id = 6 AND status = 1 AND p.p_id IN (SELECT pov.p_id FROM product_option_value pov WHERE pov.p_id AND p.quantity != pov.quantity AND pov.quantity = 0 GROUP BY pov.p_id)) THEN 1 ELSE NULL END) AS "vex-Partial-Soldout",
COUNT(CASE WHEN (vendor_id = 6 AND status = 1 AND p.quantity = 0) THEN 1 ELSE NULL END) AS "vex-Soldout",
COUNT(CASE WHEN (vendor_id = 5 AND status = 1) THEN 1 ELSE NULL END) AS "vey-DXB",
COUNT(CASE WHEN (vendor_id = 5 AND status = 1 AND p.p_id IN (SELECT pov.p_id FROM product_option_value pov WHERE pov._id AND p.quantity != pov.quantity AND pov.quantity = 0 GROUP BY pov.p_id)) THEN 1 ELSE NULL END) AS "vey-Partial-Soldout",
COUNT(CASE WHEN (vendor_id = 5 AND status = 1 AND p.quantity = 0) THEN 1 ELSE NULL END) AS "vey-Soldout"
FROM product p
Table Structure
//Product p table
* p_id * model * vendor_id * status * Quantity *
* 1001 * HB1 * 1 * 1 * 10 *
* 1002 * HB2 * 6 * 1 * 17 *
* 1003 * HB3 * 5 * 1 * 19 *
* 1004 * HB4 * 2 * 1 * 3 *
* 1005 * HB5 * 1 * 1 * 8 *
* 1006 * HB6 * 6 * 1 * 55 *
* 1007 * HB7 * 3 * 1 * 32 *
* 1008 * HB8 * 5 * 1 * 6 *
* 1009 * HB9 * 5 * 1 * 10 *
//product_option_value pov table
* pov_id * p_id * opt_id * quantity *
* 1 * 1001 * 11 * 10 *
* 2 * 1002 * 11 * 17 *
* 3 * 1003 * 11 * 0 *
* 4 * 1004 * 11 * 3 *
* 5 * 1005 * 11 * 8 *
* 6 * 1006 * 11 * 0 *
* 7 * 1007 * 11 * 32 *
* 8 * 1008 * 11 * 6 *
* 9 * 1009 * 11 * 0 *
Group by is necessary in subquery so left join is also not solving the issue.
The logic in the subqueries in quite painful to follow, so I'm not sure I have it 100% correct. For instance, the sample data only seems to have one row per product, but I don't know if that is really the case. Or what opt_id is, because that would seem to be useful in a query that uses the pov table.
That said, it appears that you just need JOIN and GROUP BY to get what you want -- a query that is much simpler and should be faster in any database.
In the following query, I have also split the two vendors on different rows. That is at least helpful to get the logic correct:
SELECT vendor_id,
COUNT(DISTINCT p.p_id) AS num_products,
SUM(CASE WHEN p.quantity <> pov.quantity AND pov.quantity = 0 THEN 1 ELSE 0 END) as partial_soldout,
COUNT(DISTINCT CASE WHEN p.quantity = 0 THEN p.p_id END) as soldout
FROM product p LEFT JOIN
product_option_value pov
ON pov.p_id = p.p_pid
WHERE p.vendor_id IN (5, 6) AND p.status = 1
GROUP BY p.vendor_id;
You have to remove the "pov.p_id AND" just after the where clause from the two expressions which calculate "vex-Partial-Soldout" and "vey-Partial-Soldout". Then it is working on postgreSQL9.6 and output is matching with your sqlserver version output.
SELECT COUNT(CASE WHEN (vendor_id = 6 AND status = 1) THEN 1 ELSE NULL END) AS "vex",
COUNT(CASE WHEN (vendor_id = 6 AND status = 1 AND p.p_id IN (SELECT pov.p_id FROM product_option_value pov WHERE p.quantity != pov.quantity AND pov.quantity = 0 GROUP BY pov.p_id)) THEN 1 ELSE NULL END) AS "vex-Partial-Soldout",
COUNT(CASE WHEN (vendor_id = 6 AND status = 1 AND p.quantity = 0) THEN 1 ELSE NULL END) AS "vex-Soldout",
COUNT(CASE WHEN (vendor_id = 5 AND status = 1) THEN 1 ELSE NULL END) AS "vey-DXB",
COUNT(CASE WHEN (vendor_id = 5 AND status = 1 AND p.p_id IN (SELECT pov.p_id FROM product_option_value pov WHERE p.quantity != pov.quantity AND pov.quantity = 0 GROUP BY pov.p_id)) THEN 1 ELSE NULL END) AS "vey-Partial-Soldout",
COUNT(CASE WHEN (vendor_id = 5 AND status = 1 AND p.quantity = 0) THEN 1 ELSE NULL END) AS "vey-Soldout"
FROM product p
Note: I did not paid much attention to your logic, as a best practice please avoid writing select statements within your select.

sql server 2008 running totals between 2 dates

I need to get running totals between 2 dates in my sql server table and update the records simultaneoulsy. My data is as below and ordered by date,voucher_no
DATE VOUCHER_NO OPEN_BAL DEBITS CREDITS CLOS_BAL
-------------------------------------------------------------------
10/10/2017 1 100 10 110
12/10/2017 2 110 5 105
13/10/2017 3 105 20 125
Now if i insert a record with voucher_no 4 on 12/10/2017 the output should be like
DATE VOUCHER_NO OPEN_BAL DEBITS CREDITS CLOS_BAL
------------------------------------------------------------------
10/10/2017 1 100 10 110
12/10/2017 2 110 5 105
12/10/2017 4 105 4 109
13/10/2017 3 109 20 129
I have seen several examples which find running totals upto a certain date but not between 2 dates or from a particular date to end of file
You should consider changing your database structure. I think it will be better to keep DATE, VOUCHER_NO, DEBITS, CREDITS in one table. And create view to calculate balances. In that case you will not have to update table after each insert. In this case your table will look like
create table myTable (
DATE date
, VOUCHER_NO int
, DEBITS int
, CREDITS int
)
insert into myTable values
('20171010', 1, 10, null),( '20171012', 2, null, 5)
, ('20171013', 3, 20, null), ('20171012', 4, 4, null)
And view will be
;with cte as (
select
DATE, VOUCHER_NO, DEBITS, CREDITS, bal = isnull(DEBITS, CREDITS) * case when DEBITS is null then -1 else 1 end
, rn = row_number() over (order by DATE, VOUCHER_NO)
from
myTable
)
select
a.DATE, a.VOUCHER_NO, a.DEBITS, a.CREDITS
, OPEN_BAL = sum(b.bal + case when b.rn = 1 then 100 else 0 end) - a.bal
, CLOS_BAL = sum(b.bal + case when b.rn = 1 then 100 else 0 end)
from
cte a
join cte b on a.rn >= b.rn
group by a.DATE, a.VOUCHER_NO, a.rn, a.bal, a.DEBITS, a.CREDITS
Here's another solution if you can not change your db structure. In this case you must run update statement each time after inserts. In both cases I assume that initial balance is 100 while recalculation
create table myTable (
DATE date
, VOUCHER_NO int
, OPEN_BAL int
, DEBITS int
, CREDITS int
, CLOS_BAL int
)
insert into myTable values
('20171010', 1, 100, 10, null, 110)
,( '20171012', 2, 110, null, 5, 105)
, ('20171013', 3, 105, 20, null, 125)
, ('20171012', 4, null, 4, null, null)
;with cte as (
select
DATE, VOUCHER_NO, DEBITS, CREDITS, bal = isnull(DEBITS, CREDITS) * case when DEBITS is null then -1 else 1 end
, rn = row_number() over (order by DATE, VOUCHER_NO)
from
myTable
)
, cte2 as (
select
a.DATE, a.VOUCHER_NO
, OPEN_BAL = sum(b.bal + case when b.rn = 1 then 100 else 0 end) - a.bal
, CLOS_BAL = sum(b.bal + case when b.rn = 1 then 100 else 0 end)
from
cte a
join cte b on a.rn >= b.rn
group by a.DATE, a.VOUCHER_NO, a.rn, a.bal
)
update a
set a.OPEN_BAL = b.OPEN_BAL, a.CLOS_BAL = b.CLOS_BAL
from
myTable a
join cte2 b on a.DATE = b.DATE and a.VOUCHER_NO = b.VOUCHER_NO

SQL calculations based on column value

I have a table transactions:
client_id Amount payment ref contract type
1 300 MTV 1
1 300 MTV 1
1 300 MTV 1
1 150 ML 1
2 150 ML 2
2 150 ML 2
2 150 ML 2
2 150 ML 2
If a client is on contract 1, then their total payments should be 3 x MTV(300) and 3 x ML(150). If they are on contract 2, then they pay 6 x ML(150).
I am trying to figure out how to get the total number of payments remaining for each client based on their contract type. For example client_id = 1:
client_id type Total Paid Payments remaining
1 MTV 900 0
1 ML 150 2
I can do the first three columns using this:
SELECT `client_id`,
`payment ref` AS `type`,
SUM(`Amount`) as `Total Paid`
FROM transactions
WHERE client_id = 1
GROUP BY type;
How do I add on the payments remaining column?
CASE WHEN `contract type` = 1 THEN (3 - COUNT(MTV)... ?
You were pretty close, there was an issue with the GROUP BY clause not including client_id and payment ref:
SELECT
client_id,
payment ref AS type,
SUM(Amount) as 'Total Paid',
CASE
WHEN contract type = 1 THEN (3 - COUNT(*))
WHEN contract type = 2 THEN (6 - COUNT(*))
END as 'Payments remaining'
FROM transactions
WHERE client_id = 1
GROUP BY client_id,
payment ref;
could use case when and group by
select
client_id
, payment
, case
when `contract type` = 1 and `payment ref` = 'MTV' then 3*300
when `contract type` = 1 and `payment ref` = 'ML' then 3*150
when `contract type` = 2 then 3*150
end as to_pay
, sum(Amount) payed
, case
when `contract type` = 1 and `payment ref` = 'MTV' then 3*300/SUM(Amount)
when `contract type` = 1 and `payment ref` = 'ML' then 3*150/sum(Amount)
when `contract type` = 2 then 3*150 / sum(Amount)
end number_of
end as `Payments remaining`
from my_table
group by client_id, `contract type`, `payment ref`
Try the below query
select *
,case contract_type
when 1 then 3-paidCount
when 2 then 6-paidCount
End
from (
select client_id , payment_ref , contract_type,sum(Amount)TotalPaid ,count(*) paidCount
FROM transactions
group by client_id , payment_ref , contract_type
) t

Why MySQL full outer join returns nulls?

Why MySQL full outer join returns nulls?
Hi
I have the following data:
s_id,date,p_id,amount_sold
1, '2015-10-01', 1, 10
2, '2015-10-01', 2, 12
7, '2015-10-01', 1, 11
3, '2015-10-02', 1, 11
4, '2015-10-02', 2, 10
5, '2015-10-15', 1, 22
6, '2015-10-16', 2, 20
8, '2015-10-22', 3, 444
and i want my query to output something like this: (A = sum of amount_sold for p_id=1 for that date,B = sum of amount_sold for p_id=2 for that date)
date,A,B,Difference
'2015-10-01',21,12,9
'2015-10-02',11,10,1
'2015-10-15',22,0,22
'2015-10-01',0,20,-20
I tried with this query, but the order its returning is having NULLS and the output is wrong:
SELECT A.p_id,A.date,sum(A.amount_sold) A,B.Bs, (sum(A.amount_sold) - B.Bs) as difference FROM sales as A
LEFT JOIN (
SELECT SUM( amount_sold ) Bs,p_id,s_id, DATE
FROM sales
WHERE p_id =2
group by date
) as B ON A.s_id = B.s_id
where A.p_id=1 or B.p_id=2
group by A.date, A.p_id
UNION
SELECT A.p_id,A.date,sum(A.amount_sold) A,B.Bs, (sum(A.amount_sold) - B.Bs) as difference FROM sales as A
RIGHT JOIN (
SELECT SUM( amount_sold ) Bs,p_id,s_id, DATE
FROM sales
WHERE p_id =2
group by date
) as B ON A.s_id = B.s_id
where B.p_id=2
group by A.date, A.p_id
It returned:
p_id date A Bs difference
1 2015-10-01 21 NULL NULL
2 2015-10-01 12 12 0
1 2015-10-02 11 NULL NULL
2 2015-10-02 10 10 0
1 2015-10-15 22 NULL NULL
2 2015-10-16 20 20 0
What am i doing wrong here? and what is the correct way of doing it? any help would be appreciated.
A full join isn't needed. You can use conditional aggregation instead:
select
date,
sum(case when p_id = 1 then amount_sold else 0 end) a,
sum(case when p_id = 2 then amount_sold else 0 end) b,
sum(case when p_id = 1 then amount_sold else 0 end)
- sum(case when p_id = 2 then amount_sold else 0 end) difference
from sales
where p_id in (1,2)
group by date

MySQL: Using alias as a column

I have this query:
select qa_returns_items.item_code,
(CASE status_code
WHEN 11 THEN (qa_returns_items.item_quantity - qa_returns_residues.item_quantity)
WHEN 12 THEN (qa_returns_items.item_quantity + qa_returns_residues.item_quantity) END) as total_ecuation ,
qa_returns_residues.item_unitprice,
( qa_returns_residues.item_unitprice * total_ecuation) as item_subtotal,
(qa_returns_residues.item_discount * item_quantity) as item_discount,
( ( qa_returns_residues.item_unitprice * total_ecuation) -
(qa_returns_residues.item_discount * item_quantity) ) as item_total
from qa_returns_residues, qa_returns_items
where
total_ecuation > 0
AND qa_returns_items.item_code = qa_returns_residues.item_code;
It shows me the error: Unknown column 'total_ecuation' in 'field list'
how I can use the alias as a column?
Consider using a subquery. I've added table aliases to make the query more readable:
select *
, item_unitprice * total_ecuation as item_subtotal
, (item_unitprice * total_ecuation) - item_discount as item_total
from (
select ri.item_code
, case status_code
when 11 then ri.item_quantity - rr.item_quantity
when 12 then ri.item_quantity + rr.item_quantity
end as total_ecuation
, rr.item_unitprice
, rr.item_quantity
, rr.item_discount * rr.item_quantity as item_discount
from qa_returns_residues rr
join qa_returns_items ri
on ri.item_code = rr.item_code
) as SubQueryAlias
where total_ecuation > 0
I'm afraid you have to rewrite your query to use a named subquery, or repeat the whole case statement in the where clause...