i'm having difficulties on query 2 tables & change the data on those 2 tables.
Here's what i wanted to do.
Get Table B "Max Qty" - Table A ("Actual Qty" - "WIP Qty") = Table B "Topup Qty"
Then change "Signal" value into NULL or 1-4 legend base on (("Actual Qty" - "WIP Qty") / "Max Qty") x 100%
Legend
NULL = More than or equal to 60%
1 = Less than or equal to 60%
2 = Less than or equal to 50%
3 = Less than or equal to 30%
4 = Less than or equal to 0%
From this:
TABLE A
- Products Actual Qty WIP QTY
- Product A 5 0
- Product B 5 0
- Product C 733 72
- Product D 532 90
- Product E 510 360
TABLE B
- MIN QTY MAX QTY TOPUP QTY SIGNAL
- 100 1000 NULL NULL
- 329 857 NULL NULL
- 393 1025 NULL NULL
- 262 683 NULL NULL
- 319 832 NULL NULL
To become like this:
TABLE A
- Products Actual Qty WIP QTY
- Product A 5 0
- Product B 5 0
- Product C 733 72
- Product D 532 90
- Product E 510 360
TABLE B
- MIN QTY MAX QTY TOPUP QTY SIGNAL
- 100 1000 995 4
- 329 857 852 4
- 393 1025 220 NULL
- 262 683 61 NULL
- 319 832 680 4
I am assuming that TableB has some relation to TableA
This will not be possible if there is no way to relate between them.
DECLARE #tableA TABLE(Products VARCHAR(50), Actual_Qty INT, WIP_Qty INT)
DECLARE #tableB TABLE(Products VARCHAR(50), Min_Qty INT, Max_Qty INT, Topup_Qty INT, Signal INT)
INSERT INTO #tableA VALUES
('Product A',5, 0),
('Product B', 5, 0),
('Product C', 733 , 72),
('Product D', 532 , 90),
('Product E', 510 , 360)
INSERT INTO #tableB VALUES
('Product A',100, 1000,995, 4),
('Product B',329, 857 ,852, 4),
('Product C',393, 1025,220, NULL),
('Product D',262, 683 ,61 , NULL),
('Product E',319, 832 ,680, 4)
SELECT A.Products,A.Actual_Qty,A.WIP_Qty,A.Actual_Qty-A.WIP_Qty Topup,'>' [ ],B.Products,B.Min_Qty,B.Max_Qty,B.Topup_Qty,B.Signal, 'now calculate > ' [ ]
, CONVERT(MONEY,(A.Actual_Qty-A.WIP_Qty )*100)/B.Max_Qty SignalTest
, CASE
WHEN CONVERT(MONEY,(A.Actual_Qty-A.WIP_Qty )*100)/B.Max_Qty >= 60 THEN 1
WHEN CONVERT(MONEY,(A.Actual_Qty-A.WIP_Qty )*100)/B.Max_Qty BETWEEN 50 AND 60 THEN 2
WHEN CONVERT(MONEY,(A.Actual_Qty-A.WIP_Qty )*100)/B.Max_Qty BETWEEN 30 AND 50 THEN 3
WHEN CONVERT(MONEY,(A.Actual_Qty-A.WIP_Qty )*100)/B.Max_Qty < 30 THEN 4
END Signal
FROM #tableA A
INNER JOIN #tableB B ON B.Products = A.Products
/*Here is the update but, you can switch the tables for your tables*/
UPDATE B
SET B.Signal = (SELECT CASE
WHEN CONVERT(MONEY,(A.Actual_Qty-A.WIP_Qty )*100)/B.Max_Qty >= 60 THEN 1
WHEN CONVERT(MONEY,(A.Actual_Qty-A.WIP_Qty )*100)/B.Max_Qty BETWEEN 50 AND 60 THEN 2
WHEN CONVERT(MONEY,(A.Actual_Qty-A.WIP_Qty )*100)/B.Max_Qty BETWEEN 30 AND 50 THEN 3
WHEN CONVERT(MONEY,(A.Actual_Qty-A.WIP_Qty )*100)/B.Max_Qty < 30 THEN 4
END Signal)
FROM #tableA A
INNER JOIN #tableB B ON B.Products = A.Products
SELECT
*
FROM #tableB
Related
I am getting the sum of all the rows in registration table. Table structure looks like this:
row_id row_registration_fee row_amount row_class row_user_id
1 200 1000 18 1
2 200 2510 18 1
3 0 1600 19 2
4 0 1500 19 1
5 200 1254 19 3
6 200 3000 19 1
7 200 2000 19 1
8 0 100 20 1
9 0 300 20 2
A user can have multiple registration fee. And I need to get the sum of all the row_registration_fee by row_class. The result should be like this:
row_registration_fee row_class
200 18
400 19
0 20
My select :
SELECT (COUNT(DISTINCT(row_user_id))* 200) as 'fee'
FROM registration
WHERE row_registration_fee > 0
GROUP BY row_class
Is there a better query here that can give a result like the above sample?
The result will be displayed in table rows using foreach loop in PHP. As of now, it will only give me two results for the registration fee, the row_class 18 and row_class 19 it excludes the row_class 20 because it only selects the user with a fee.
Additional explanation: The user with 2 or more registration fees should count only as one if the user has a total of 400 fees it should sum only 200.
Another approach might be to find the most recent row_id. In this case I have altered the data so that the first entry appears to be an error (fee = 300) followed by the second entry for the correct amount .
drop table if exists t;
create table t(
row_id int,row_registration_fee int,row_amount int, row_class int, row_user_id int);
insert into t values
(1 , 300 , 1000 , 18 , 1),
(2 , 200 , 2510 , 18 , 1),
(3 , 0 , 1600 , 19 , 2),
(4 , 0 , 1500 , 19 , 1),
(5 , 200 , 1254 , 19 , 3),
(6 , 200 , 3000 , 19 , 1),
(7 , 200 , 2000 , 19 , 1),
(8 , 0 , 100 , 20 , 1),
(9 , 0 , 300 , 20 , 2)
;
select sum(row_registration_fee),row_class
from
(
select t.row_class,t.row_registration_fee
from t
where t.row_id = (select max(row_id) from t t1 where t1.row_user_id = t.row_user_id and t1.row_class = t.row_class)
) a
group by row_class;
+---------------------------+-----------+
| sum(row_registration_fee) | row_class |
+---------------------------+-----------+
| 200 | 18 |
| 400 | 19 |
| 0 | 20 |
+---------------------------+-----------+
3 rows in set (0.00 sec)
To get those expected results then it seems to me that you first need to get the unique records per (row_registration_fee, row_class, row_user_id) tupple.
You can use a sub-query with a DISTINCT for that.
Then sum the row_registration_fee.
SELECT
SUM(row_registration_fee) as fee,
row_class
FROM
(
SELECT DISTINCT row_class, row_user_id, row_registration_fee
FROM registration
) q
GROUP BY row_class
Or via a GROUP BY and get the MAX fee.
SELECT
SUM(max_fee) as fee,
row_class
FROM
(
SELECT
row_class, row_user_id,
MAX(row_registration_fee) as max_fee
FROM registration
GROUP BY
row_class, row_user_id
) q
GROUP BY row_class
But to fix your current query, you could remove that WHERE clause.
And then use a CASE WHEN to return NULL on a zero row_registration_fee.
Because a count by value doesn't count the NULL's.
SELECT
COUNT(DISTINCT CASE WHEN row_registration_fee = 0 THEN row_user_id END) * 200 as fee,
row_class
FROM registration
GROUP BY row_class
You need to group by two columns and take sum:
select row_class, sum(row_registration_fee)
from registration
group by row_class, row_user_id
SELECT SUM(row_registration_fee), row_class, row_user_id
FROM registration
WHERE row_registration_fee > 0
GROUP BY row_class, row_user_id;
Yeah, group by two columns you can get per class and user.
I am trying to match data where the record_status_id flag is changed from 2 to 1 in more than 90 days. The query should ignore the records which changes from 1 to 2. I have taken help and resources from this question.
I have following data sets:
revision record_id record_status_id last_updated_date
239 59 1 2016-01-19 10:18:00
284 59 2 2016-01-19 12:12:00
302 59 2 2016-01-20 15:18:00
304 59 2 2016-01-25 16:26:00
305 59 1 2016-05-24 16:29:00
307 59 2 2016-05-25 11:33:00
309 59 1 2016-07-07 10:15:00
310 59 2 2016-08-07 12:44:00
489 59 1 2016-11-11 02:12:00
492 59 1 2016-11-11 05:25:00
502 59 2 2016-11-12 10:12:00
504 59 2 2016-12-05 11:23:00
509 59 1 2016-12-11 12:24:00
519 59 1 2016-12-11 14:30:00
524 59 1 2016-12-11 15:36:00
674 59 1 2016-12-11 17:45:00
Schema and Data:
CREATE TABLE IF NOT EXISTS record_history (
`revision` INT(11) NOT NULL,
`record_id` BIGINT(20) NOT NULL,
`creation_date` DATETIME NULL DEFAULT NULL,
`record_status_id` BIGINT(20) NULL DEFAULT NULL,
`last_updated_date` DATETIME NULL DEFAULT NULL,
PRIMARY KEY USING BTREE (`record_id`, `revision`))
ENGINE = InnoDB;
INSERT INTO record_history(revision,record_id,creation_date,record_status_id,last_updated_date) VALUES
( 239,59,'2016-01-18 16:23:00',1,'2016-01-19 10:18:00'),
( 284,59,'2016-01-18 16:23:00',2,'2016-01-19 12:12:00'),
( 302,59,'2016-01-18 16:23:00',2,'2016-01-20 15:18:00'),
( 304,59,'2016-01-18 16:23:00',2,'2016-01-25 16:26:00'),
( 305,59,'2016-01-18 16:23:00',1,'2016-05-24 16:29:00'),
( 307,59,'2016-01-18 16:23:00',2,'2016-05-25 11:33:00'),
( 309,59,'2016-01-18 16:23:00',1,'2016-07-07 10:15:00'),
( 310,59,'2016-01-18 16:23:00',2,'2016-08-07 12:44:00'),
( 489,59,'2016-01-18 16:23:00',1,'2016-11-11 02:12:00'),
( 492,59,'2016-01-18 16:23:00',1,'2016-11-11 05:25:00'),
( 502,59,'2016-01-18 16:23:00',2,'2016-11-12 10:12:00'),
( 504,59,'2016-01-18 16:23:00',2,'2016-12-05 11:23:00'),
( 509,59,'2016-01-18 16:23:00',1,'2016-12-11 12:24:00'),
( 519,59,'2016-01-18 16:23:00',1,'2016-12-11 14:30:00'),
( 524,59,'2016-01-18 16:23:00',1,'2016-12-11 15:36:00'),
( 674,59,'2016-01-18 16:23:00',1,'2016-12-11 17:45:00');
So far, I have used following query:
SELECT revision, record_id, record_status_id, last_updated_date FROM record_history AS a
WHERE a.record_status_id = 2
and a.record_status_id <> ( SELECT b.record_status_id FROM record_history AS b
WHERE a.record_id = b.record_id
AND a.last_updated_date < b.last_updated_date
-- AND DATEDIFF(b.last_updated_date, a.last_updated_date) > 90
-- and b.last_updated_date > DATE_ADD(a.last_updated_date,INTERVAL 90 DAY)
LIMIT 1
);
to obtain;
revision record_id record_status_id last_updated_date
304 59 2 2016-01-25 16:26:00
307 59 2 2016-05-25 11:33:00
310 59 2 2016-08-07 12:44:00
504 59 2 2016-12-05 11:23:00
Further down, I want to filter down the records where the date difference between where the record_status_id flag changes from 2 to 1 is greater than 90.
I have commented the DATEDIFF and DATE_ADD as it doesn't seem to be working. Ideally, it should have worked for me but its not. My desired result is given below as the flag of revision 304 and 305 is changed from 2 to 1 after 90 days and so is the case for record with revision 310;
revision record_id record_status_id last_updated_date
304 59 2 2016-01-25 16:26:00
310 59 2 2016-08-07 12:44:00
Thanks for your effort. I don't know whats causing the erratic behaviour with DATEDIFF and DATE_ADD. If I uncomment these keyword lines, the filtered records expands instead of narrowing to the desired result. I have created sample data in http://rextester.com/EKHGF57315 along with the query I have used.
With the help of this question in stackoverflow, I was able to solve my question. Here's my solution:
SELECT revision, record_id, record_status_id, last_updated_date FROM record_history AS a
WHERE a.record_status_id = 2
and a.record_status_id <> ( SELECT T.record_status_id FROM record_history AS T
WHERE a.record_id = T.record_id
AND a.last_updated_date < T.last_updated_date
LIMIT 1
)
and a.revision in (
SELECT T.revision
-- SELECT T.revision, T.record_id, T.record_status_id, T.last_updated_date, DATEDIFF(T.NextDate, T.last_updated_date) as days
FROM (SELECT T1.revision, T1.record_id, T1.record_status_id, T1.last_updated_date,
( SELECT T2.last_updated_date
FROM record_history T2
WHERE T2.record_id = T1.record_id
AND T2.last_updated_date > T1.last_updated_date limit 1
) AS NextDate
FROM record_history T1
) AS T
WHERE DATEDIFF(T.NextDate, T.last_updated_date) > 90
);
Hope this will be useful for fellow users.
I am trying to write a stored procedure to display (fid, name,tel,income,balance,loan_amount, child_count) from two tables
Family(fid,name,tel,income,good_credit,balance)
Children(cid,name,age,fid). The function should be able to predict who can be a potential customer based on the following criteria:
Good credit, balance>=3000, child_count:total number of children between age 18 and 22, income:40000 and loan_amount = income * 0.3 * child_count
Family table
fid name tel income good_credit balance
1 aaa1 111 15000 1 1000
2 aaa2 211 25000 0 10000
3 aaa3 311 80000 0 1000
4 aaa4 411 40000 1 7000
Children table
cid name age fid
1 bbb1 14 3
2 bbb2 14 15
3 bbb3 19 16
4 bbb4 18 9
My code looks like this, but i got an error "subquery returns more than one row"
delimiter $$
CREATE PROCEDURE procc()
BEGIN
declare loan_amount int (200);
declare child_count int (200);
set child_count = (select count(age) from Children,Family where age between 18 and 22 );
set loan_amount = (select income from Children CV,Family DV where DV.FID = CV.FID);
if (child_count is not null) then select cf.FID as FID, cf.Name as Name, cf.TEL as TEL, cf.income as income, cf.balance as balance, child_count, loan_amount * 0.3 * child_count from Family cf,Children cc
where cf.FID = cc.FID and good_credit = 1 and income >= 40000 and balance = 3000;
end if;
end$$
delimiter ;
I have to design an optimized MySQL query for generating a report based on 2 tables.
I have 2 tables one for services and another for payments. I accept user specific criteria for services and based on that I have to report services and corresponding payments. These transactions from 2 different tables will be in order of service dates and corresponding payments in order of payment dates. Along with that, I also have to report any advance payments paid on account (in database terms payments not linked to any particular service)
Currently I run one query for selecting services and unlinked payments using UNION of 2 tables based on given criteria. Then I run separate query for each service related payment through a loop.
Is there any way I can get all these transactions via a single query and that too in desired order.
Here are the relevant columns of 2 tables.
service table
id (PK)
account_no
date
service_amount
tran_type
payment table
id
account_no
date
pmt_amount
service_id (FK to service table nulls acceptable)
tran_type
Here are the queries I am trying
Query 1
select account_no, id, date, service_amount, tran_type
from service where <user specified criteria like date range>
UNION
select account_no, id, date, pmt_amount, tran_type
from payment where service_id is null and
<user specified criteria like date range>
order by date
Query2
This query is run on individual services on result of above query ( tran_type is service)
select account_no, id, date, pmt_amount, tran_type
from payment where service_id= <specific id>
order by date
Service table Data
ID Item_Typ Date Amt Acct#
1 SVC 11/12/2015 10 1
2 SVC 11/20/2015 20 1
3 SVC 12/13/2015 40 1
4 SVC 4/1/2016 30 1
Payment table Data
ID Svc_ID Item_Typ Date Amt Acct#
1 1 PMT 11/15/2015 5 1
2 1 PMT 11/15/2015 5 1
3 2 PMT 11/25/2015 40 1
4 3 PMT 12/28/2015 35 1
5 2 PMT 12/30/2015 -15 1
7 NULL PMT 1/1/2016 12 2
8 NULL PMT 3/1/2016 35 3
Query 1 Result
ID Item_Typ Date Amt Acct#
1 SVC 11/12/2015 10 1
2 SVC 11/20/2015 20 1
3 SVC 12/13/2015 40 1
4 SVC 4/1/2016 30 1
7 PMT 1/1/2016 12 2
8 PMT 3/1/2016 35 3
Final result after fetching payments for all query result related services
tranTyp Date Amt Acct#
SVC 11/12/2015 10 1
PMT 11/15/2015 5 1
PMT 11/15/2015 5 1
SVC 11/20/2015 20 1
PMT 11/25/2015 40 1
PMT 12/30/2015 -15 1
SVC 12/13/2015 40 1
PMT 12/28/2015 35 1
drop table if exists service;
create table service (ID int, Item_Typ varchar(3), `Date` date, Amt int, Acct int);
insert into service values
(1, 'SVC', '2015-11-12', 10 , 1),
(2, 'SVC', '2015-11-20', 20 , 1),
(3, 'SVC', '2015-12-13', 40 , 1),
(4, 'SVC', '2016-01-04', 30 , 1),
(5, 'SVC', '2015-10-04', 50 , 1)
drop table if exists payment;
create table payment(ID INT, Svc_ID INT, Item_Typ VARCHAR(3), `Date` DATE, Amt INT, Acct INT);
INSERT INTO payment values
(1, 1 , 'PMT', '2015-11-15', 5 , 1),
(2, 1 , 'PMT', '2015-11-15', 5 , 1),
(3, 2 , 'PMT', '2015-11-25', 40 , 1),
(4, 3 , 'PMT', '2015-12-28', 35 , 1),
(5, 2 , 'PMT', '2015-12-30', -15 ,1),
(7, NULL , 'PMT', '2016-01-01', 12 , 2),
(8, NULL , 'PMT', '2016-03-01', 35 , 3);
MariaDB [sandbox]> select * from
-> (
-> select 1 as typ,id,Item_typ,`date`, `date` as svc_date,amt,acct from service
-> union all
-> select 2,p.svc_id,p.Item_typ,p.`date`,
-> case when s.id is null then now()
-> else s.`date`
-> end as svc_date,
-> p.amt, p.acct from payment p
-> left join service s on p.svc_id = s.id
-> ) s
->
-> order by s.svc_date,s.acct,s.typ,s.id
-> ;
I have two different tables :
Tank & FillingStations
In which one tank can be attached to many fillingstations.
Suppose:
SrNo TankID TankName TANK_Balance FillingStation_ID FS_NAme BALANCE
1 1 Tank1 5000 A11 FSA11 1545
2 1 Tank1 5000 A12 FSA12 1000
3 1 Tank1 5000 A13 FSA13 800
And i want to get a report as like :
SrNo TankID TankName TANK_Balance A11 BAL1 A12 BAL2 A13 BAL3 TOTAL
1 1 Tank1 5000 FSA11 1545 FSA12 1000 FSA13 800 3345
Try like this,
DECLARE #Table TABLE (
SrNo INT
,TankID INT
,TankName VARCHAR(10)
,TANK_Balance INT
,FillingStation_ID VARCHAR(10)
,FS_NAme VARCHAR(10)
,BALANCE INT
)
insert into #Table values
(1,1,'Tank1',5000,'A11','FSA11',1545)
,(2,1,'Tank1',5000,'A12','FSA12',1000)
,(3,1,'Tank1',5000,'A13','FSA13',800)
SELECT min(SrNo) as SrNo, TankID
,TankName
,TANK_Balance
,max([A11]) AS [A11]
,max([BAL1]) AS [BAL1]
,max([A12]) AS [A12]
,max([BAL2]) AS [BAL2]
,max([A13]) AS [A13]
,max([BAL3]) AS [BAL3]
,max([BAL1])+max([BAL2])+max([BAL3]) as Total
FROM (
SELECT SrNo,TankID
,TankName
,TANK_Balance
,FillingStation_ID
,replace(FillingStation_ID, 'A1', 'BAL') AS bFillingStation_ID
,FS_NAme
,BALANCE
FROM #Table
) s
pivot(Max(FS_NAme) FOR FillingStation_Id IN (
[A11]
,[A12]
,[A13]
)) t
pivot(Max(BALANCE) FOR bFillingStation_Id IN (
[BAL1]
,[BAL2]
,[BAL3]
)) t1
GROUP BY TankID
,TankName
,TANK_Balance