Create Mysql view from two table not working - mysql

I have two table
ORDER
prod_id qty gst gst_rate
1 25 yes 18
1 25 no 0
2 10 yes 12
3 5 no 0
RETURN
prod_id add less gst_rate
1 5 0 0
1 10 0 18
3 0 2 0
About the table ORDER
Product 1 have order 25 with gst 18% and order 25 without gst. Product
2 have order 10 with gst 12%. Product 3 have order 5 without gst.
About the table Return
Product 1 without gst have extra qty 5. Product 1 with gst have extra
qty 10. Product 3 (no gst) have less qty 2. Product 2 have no extra or
less qty.
So I have to create a VIEW for each entry in ORDER table
Result should look like this
prod_id qty gst_rate add less
1 25 18 10 0
1 25 0 5 0
2 10 12 0 0
3 5 0 0 2
What I tried is:
SELECT ord.prod_id, ord.qty, ord.gst_rate, ret.add, ret.less FROM order ord LEFT JOIN (SELECT case when ord.gst='no' then (select sum(add) from return,order where order.prod_id=return.prod_id and return.gst_rate=0) else (select sum(add) from return,order where order.prod_id=return.prod_id and return.gst_rate!=0) end as add FROM return) as ret ON ret.prod_id=ord.prod_id
But it is not working..

you query could be refactored avoiding subquery ..
SELECT ord.prod_id, ord.qty, ord.gst_rate,
case when rd.gst='no' then t1.sum_add else t2.sum_add end as add
FROM order ord
LEFT JOIN (
select prod_id, sum(add) as sum_add
from return
INNER JOIN order ON order.prod_id=return.prod_id and return.gst_rate=0
GROUP BY prod_id
) t1 on t1.prod_id = ord.prod_id
LEFT JOIN (
select prod_id, sum(add) as sum_add
from return
INNER JOIN order ON order.prod_id=return.prod_id and return.gst_rate!=0
GROUP BY prod_id
) t2 on t2.prod_id = ord.prod_id
(the less was not in you code so i have omitted by select )

Related

MySQL join next lower value from other table

I've the two tables orders
id article amount
1 1 1
2 2 50
and prices
id article min_amount price
1 1 1 42.99
2 2 1 5.06
3 2 5 4.55
4 2 10 4.3
5 2 25 4.05
6 2 100 2.66
The prices tables contains IDs of articles and a minimum amount you would have to buy to get a bulk discount (which would change the price for the order). I would like to join prices into orders, so that the result looks like:
id article amount price
1 1 1 42.99
2 2 50 4.05
The order id 2 is above the minimum (25) to get the article for 4.05€, but still below 100 at which you would get a bigger discount, so the query would to have pick the next-lower value.
I've tried this query so far
SELECT
orders.id AS id,
orders.article,
orders.amount,
prices.price,
(orders.amount - prices.min_amount) AS discount_diff
FROM orders
LEFT JOIN prices ON (prices.article = orders.article) AND (prices.min_amount <= orders.amount)
which gives this result
id article amount price discount_diff
1 1 1 42.99 0
2 2 50 5.06 49
2 2 50 4.55 45
2 2 50 4.3 40
2 2 50 4.05 25
You can find this example on "js"fiddle: http://sqlfiddle.com/#!9/1b2bf/8
The query you need is this:
SELECT orders.id AS id,
orders.article,
orders.amount,
prices.price
FROM orders
INNER JOIN prices ON ( prices.article = orders.article
and prices.min_amount <= orders.amount)
INNER JOIN ( SELECT orders.article,
orders.amount,
min(prices.price) minprince
FROM orders
INNER JOIN prices ON (prices.article = orders.article
AND prices.min_amount <= orders.amount)
GROUP BY orders.article,
orders.amount) b
ON ( prices.article = b.article
AND orders.amount = b.amount
AND prices.price = b.minprince)
See it here: http://sqlfiddle.com/#!9/1b2bf/27

mySQL view to show distict value and all pertaining rows beneath it

I am using mySQL. I have a table that is updated everyday based on our sku. The sku has duplicate values because there is a pricing tier associated with it. I need to create a view that will show all the rows but only 1 sku and the associated sku rows beneath it so i can export everyday for an update in magento. Magento does not allow duplicate sku's during an import. Here is an example:
sku _tier_price_qty _tier_price_price
013964223286 10 1
50 1
100 1
9332153001025 5 1
25 1
50 1
9332153001032 5 1
25 1
50 1
9332153001063 5 1
25 1
50 1
9332153001049 5 1
25 1
50 1
640420002569 5 1
25 1
50 1
640420002538 5 1
25 1
50 1
640420002521 5 1
25 1
50 1
Although this type of formatting might be better to handle in a reporting application this query should do what you want:
select
case when x.tier_qty is not null then t.sku else null end tier_qty,
t.tier_qty,
t.tier_price
from t
left join (
select sku, min(tier_qty) tier_qty
from t
group by sku
) x on t.sku = x.sku and t.tier_qty = x.tier_qty
order by t.sku, t.tier_qty;
http://www.sqlfiddle.com/#!9/3314bd/1
Can you try this?
select case when (select MIN(tier_qty) from products where sku = o.sku) = tier_qty
then sku
else null,
tier_qty,
tier_price
from products o
order by sku, tier_qty

Mysql JOIN with extra priority column

I have two days trying to do this query with no luck.
I have two tables 'DEMAND' and 'DEMAND_STATE' (one to many relation). The table DEMAND_STATE have millions entries.
CREATE TABLE DEMAND
(
ID INT NOT NULL,
DESTINY_ID INT NOT NULL
)
CREATE TABLE DEMAND_STATE
(
ID INT NOT NULL,
PRIORITY INT NOT NULL,
QUANTITY DOUBLE NOT NULL,
CASE_ID INT NOT NULL,
DEMAND_ID INT NOT NULL,
PHASE_ID INT NOT NULL
)
The QUANTITY of the DEMAND_STATE is given according to a CASE_ID and PHASE_ID. We have 'N' PHASES in 'M' CASES. Always the same number of Phases in all Cases. We always have a initial Base Quantity called 'BASE CASE' in the Case with CASE_ID = 1.
For example to obtain quantity for Case (id=2) and Case Base (id=1)
select D.*, S.PRIORITY, S.QUANTITY, S.CASE_ID, S.DEMAND_ID, S.PHASE_ID
FROM DEMAND D
join DEMAND_STATE S on (D.ID = S.DEMAND_ID)
WHERE (S.CASE_ID = 2 OR S.CASE_ID = 1)
(paste only for id=8)
ID PRIORITY QUANTITY CASE_ID DEMAND_ID PHASE_ID
8 0 85 1 8 1
8 0 83 1 8 2
8 0 88 1 8 3
8 0 89 1 8 4
8 10 85 2 8 1
8 10 84 2 8 2
8 10 86 2 8 3
8 10 89 2 8 4
We need to obtain for all Demand in 'DEMAND' only the Quantity for Each Phase with MAX priority. The idea is no duplicate DEMAND_STATE data for each new Case creation. Only create new state rows when Demand-Case-Phase is different to Case Base. This is a new project and we accept changes in model for better performance.
I also tried with the MAX calculation. This query over DEMAND_STATE works fine but only obtain data for a concrete DEMAND_ID. Further i think this solution can be so expensive.
SELECT P.ID, P.QUANTITY, P.CASE_ID, P.DEMAND_ID, P.PHASE_ID
FROM DEMAND_STATE P
JOIN (
SELECT PHASE_ID, MAX(PRIORITY) max_priority, S.DEMAND_ID
from DEMAND_STATE S
WHERE S.DEMAND_ID = 1
AND (S.CASE_ID=1 OR S.CASE_ID=2)
GROUP BY S.PHASE_ID
) SUB
ON (SUB.PHASE_ID = P.PHASE_ID AND SUB.max_priority = P.PRIORITY)
WHERE P.DEMAND_ID = 1
GROUP BY P.PHASE_ID
The result:
ID QUANTITY CASE_ID DEMAND_ID PHASE_ID
1 86 1 1 1
2 85 1 1 2
3 81 1 1 3
8 500 2 1 4
This is the result expected:
ID ID PRIORITY QUANTITY CASE_ID PHASE_ID
8 1 0 86 1 1 (data from Case Base id=1 priority 0)
8 2 10 85 1 2 (data from Case Baseid=1 priority 0)
8 3 10 81 1 3 (data from Case Base id=1 priority 0)
8 64 10 500 2 4 (data from Case id=2 priority 10)
thank for help :)
Edit:
Result of Simon proposal:
ID QUANTITY CASE_ID DEMAND_ID PHASE_ID
1 86 1 1 1
2 85 1 1 2
3 81 1 1 3
4 84 1 1 4 (this row shouldnt exist)
8 500 2 1 4 (this is the correct row)
Also would have to join it with DEMAND
#didierc response:
ID ID MAX(S.PRIORITY) QUANTITY CASE_ID PHASE_ID
1 8 10 500 2 4
2 13 10 81 2 1
2 14 10 83 2 2
2 15 10 84 2 3
3 21 10 81 2 1
4 31 10 86 2 3
4 32 10 80 2 4
4 29 10 85 2 1
4 30 10 81 2 2
we need for each DEMAND four rows with the quantity Value. In Case Base we have four quantity and in Case 2 we only change the quantity for phase 4. We need always four rows for each demand.
Database DEMAND_STATE data:
ID PRIORITY QUANTITY CASE_ID DEMAND_ID PHASE_ID
1 0 86 1 1 1
2 0 85 1 1 2
3 0 81 1 1 3
4 0 84 1 1 4
8 10 500 2 1 4
We need to obtain for all Demand in 'DEMAND' only the Quantity for Each Phase with MAX priority
I translate the above, according to your sample result set, as:
SELECT
D.ID, S.ID, MAX(S.PRIORITY), S.QUANTITY, S.CASE_ID, S.PHASE_ID
FROM DEMAND D
LEFT JOIN DEMAND_STATE S
ON D.ID = S.DEMAND_ID
GROUP BY S.PHASE_ID, S.DEMAND_ID
Update:
To get the maximum priority for each pair(demand_id,phase_id)n we use the following query:
SELECT
DEMAND_ID, PHASE_ID, MAX(PRIORITY) AS PRIORITY
FROM DEMAND_STATE
GROUP BY DEMAND_ID, PHASE_ID
Next, to retrieve the set of phases for a given demand, just make an inner join on demand state:
SELECT S.* FROM DEMAND_STATE S
INNER JOIN (
SELECT
DEMAND_ID, PHASE_ID, MAX(PRIORITY) AS PRIORITY
FROM DEMAND_STATE
GROUP BY DEMAND_ID, PHASE_ID
) S2
USING (DEMAND_ID,PHASE_ID, PRIORITY)
WHERE DEMAND_ID = 1
If you want to limit the possible cases, include a where clause in the query S2:
SELECT S.* FROM DEMAND_STATE S
INNER JOIN (
SELECT
DEMAND_ID, PHASE_ID, MAX(PRIORITY) AS PRIORITY
FROM DEMAND_STATE
WHERE CASE_ID IN (1,2)
GROUP BY DEMAND_ID, PHASE_ID
) S2
USING (DEMAND_ID,PHASE_ID, PRIORITY)
WHERE DEMAND_ID = 1
However, your comments and update indicates that MAX(PRIORITY) does not seem very relevant after all. My understanding is that you have a base case, which may be overriden by another case in a given scenario (that scenario is the pair base case + some other case). Clarify that point in your question body if this is incorrect. If that is the case, you may change the above query by replacing PRIORITY by CASE_ID:
SELECT S.* FROM DEMAND_STATE S
INNER JOIN (
SELECT
DEMAND_ID, PHASE_ID, MAX(CASE_ID) AS CASE_ID
FROM DEMAND_STATE
WHERE CASE_ID IN (1,2)
GROUP BY DEMAND_ID, PHASE_ID
) S2
USING (DEMAND_ID,PHASE_ID, CASE_ID)
WHERE DEMAND_ID = 1
The only reason I see from having a priority is if you wish to combine more than 2 cases, and use priority to select which case will prevail depending on the phase.
You may of course prepend an inner join on DEMAND to include the related demand data.
Use of subqueries should be able to do as you wish, if I understand your question correctly. Something along the lines of the following:
SELECT
P.ID,
P.QUANTITY,
P.CASE_ID,
P.DEMAND_ID,
P.PHASE_ID
FROM DEMAND_STATE P
INNER JOIN (
-- Next level up groups it down and so gets the rows first returned for each PHASE_ID, which is the highest priority due to the subquery
SELECT
D.PHASE_ID,
D.PRIORITY,
D.DEMAND_ID
FROM (
-- Top level query to get all rows and order them in desc priority order
SELECT
S.PHASE_ID,
S.PRIORITY,
S.DEMAND_ID
FROM DEMAND_STATE S
WHERE S.DEMAND_ID IN (1) -- Update this to be whichever DEMAND_IDs you are interested in
AND S.CASE_ID IN (1,2)
ORDER BY
S.PHASE_ID ASC,
S.DEMAND_ID ASC,
S.PRIORITY DESC
) D
GROUP BY
D.PHASE_ID,
S.DEMAND_ID
) SUB
ON SUB.PHASE_ID = P.PHASE_ID
AND SUB.DEMAND_ID = P.DEMAND_ID
The top level subquery exists to get the rows you are interested in and order them in an order which allows predictable results when they are then grouped down by PHASE_ID and DEMAND_ID. This in turn allows a simple INNER JOIN to DEMAND_STATE hopefully (unless I have misunderstood your query)
This may still be expensive though depending on how much data is within that top level query.

MySQL select using row counts and grouping

I have 2 tables, orders and order_lineitems.
orders contains the order status info (sold date, invoice no, type of sale, etc)
order_lineitems contains the item(s) for each order in a one to many relationship.
Since we provide shipping info by line item, ship_date is in the order_lineitems table, null if not shipped, a date if it is shipped.
I am trying to pull the orders where all items have shipped by comparing the number of line item rows against the line item rows that have a ship date. While I have successfully pulled all that info, I am unable to make the last step, limiting the result set to include only the completely shipped orders (number of rows = number of rows where ship_date is not null).
I know I am missing something simple, but just don't see it..
select sum(custom.lineitems) as totalitems, sum(custom.shipped) as totalshipped,
custom.invoice, z.shipregion
from (
select a.invoice, count(a.invoice) as lineitems, 0 as shipped
from order_lineitem a
group by a.invoice
UNION ALL
select b.invoice, 0 as notshipped, count(b.ship_date) as shipped
from order_lineitem b
where b.ship_date is not null
group by b.invoice
) as custom
left join orders z on custom.invoice = z.invoice
where z.result = 0
and z.respmsg like 'Approved%'
and z.shipregion <> 'PENDING'
and z.cancelorder = 0
group by custom.invoice;
This returns a result set like so (one row for each invoice in the DB)
totalitems totalshipped invoice shipregion
4 2 1000 REGION08
1 1 10001 REGION07
1 1 10004 REGION05
3 1 10006 REGION05
2 2 10007 REGION04
1 1 10008 REGION08
7 7 10009 REGION01
1 1 1001 REGION08
What I am looking for is a result set like this - only where totalitems = totalshipped
totalitems totalshipped invoice shipregion
1 1 10001 REGION07
1 1 10004 REGION05
2 2 10007 REGION04
1 1 10008 REGION08
7 7 10009 REGION01
1 1 1001 REGION08
Use HAVING clause
SELECT a.invoice, z.shipregion, COUNT(a.invoice) AS lineitems,
SUM(CASE WHEN a.ship_date IS NOT NULL THEN 1 ELSE 0 END) AS shipped
FROM order_lineitem a
LEFT JOIN orders z ON a.invoice = z.invoice AND z.result = 0 AND z.cancelorder = 0 AND
z.respmsg LIKE 'Approved%' AND z.shipregion <> 'PENDING'
GROUP BY a.invoice HAVING lineitems = shipped
OR
SELECT a.invoice, a.shipregion, a.lineitems, a.shipped
FROM (SELECT a.invoice, z.shipregion, COUNT(a.invoice) AS lineitems,
SUM(CASE WHEN a.ship_date IS NOT NULL THEN 1 ELSE 0 END) AS shipped
FROM order_lineitem a
LEFT JOIN orders z ON a.invoice = z.invoice AND z.result = 0 AND z.cancelorder = 0 AND
z.respmsg LIKE 'Approved%' AND z.shipregion <> 'PENDING'
GROUP BY a.invoice
) AS a WHERE a.lineitems = a.shipped
One more outer query needed.
select * from
(
\\Your whole query here
) as Result
where Result.totalitems = Result.totalshipped

mysql compare 2 rows same table

I am trying to compare 2 rows and display the same ones.I did browse but was not able to find the right solution.
Table A
Count status Division
20 A 1
30 B 2
10 c 1
12 z 1
From the above table I want to display whose division is same.
Count status Division
20 A 1
10 c 1
12 z 1
Try this
Select * from TableA
Group By Division
Having Count(*) > 1
Select * from TableA
Group By Division
having Count(*) = 1
Here i used case statement , it worked for me
select CompanyCode ,'Commission Pec', Year
,sum(case when CommissionType='Commission Recevied' then JAN else 0 end)/sum(case when CommissionType='Net Payments from WM' and isnull(JAN,0)<>0 then JAN else 1 end)
from Commission_Consolidate
group by CompanyCode,Year
end