I have a query in SQL server in which I have used outer apply. Now I want to convert it so that query can run on SQL server and MySQL also.
select top 5 v.sVehicleName as VehicleNo, ll.Location
from vehicles v
outer APPLY
(select top 1 Location
from location_history
where vehicle_id = v.vehicle_id) ll
I have to covert this query so I can run on both databases.
This is my tables
create table #vehicles (vehicle_id int, sVehicleName varchar(50))
create table #location_history ( vehicle_id int, location varchar(50), date datetime)
insert into #vehicles
values
(1, 'MH 14 aa 1111'),
(2,'MH 12 bb 2222'),
(3,'MH 13 cc 3333'),
(4,'MH 42 dd 4444')
insert into #location_history
values
( 1, 'aaa', getdate()),
( 1, 'bbb', getdate()),
( 2, 'ccc', getdate()),
( 2, 'ddd', getdate()),
( 3, 'eee', getdate()),
( 3, 'fff', getdate()),
( 4, 'ggg', getdate()),
( 4 ,'hhh', getdate())
This is query which I execute in SQL server.
select v.sVehicleName as VehicleNo, ll.Location
from #vehicles v
outer APPLY
(select top 1 Location
from #location_history
where vehicle_id = v.vehicle_id) ll
This is output in SQL server.
VehicleNo
Location
MH14 aa 1111
aaa
MH12 bb 2222
ccc
MH13 cc 3333
eee
MH42 dd 4444
ggg
I want to execute this in MySQL. and I want same output mentioned above.
In this case you can use LEFT JOIN instead of OUTER APPLY. like that:
select top 5 v.sVehicleName as VehicleNo, ll.Location
from vehicles v
left join
(
select vehicle_id, min(Location) as Location
from location_history
group by vehicle_id
) ll
on ll.vehicle_id = v.vehicle_id
If you want first record from location history table for each vehicle which is present in vehicles table,
then you can use cross join.
see below e.g
create table #location (vehicle_id int, vehicle_name varchar(50))
create table #lochistory ( vehicle_id int, location varchar(50), date datetime)
insert into #location
values
(1, 'car'),
(2,'bus'),
(3,'auto'),
(4,'jeep')
insert into #lochistory
values
( 1, 'india', getdate()),
( 1, 'usa' , getdate()),
( 2, 'india', getdate())
select *from #location l
cross join
(
select top 1 * from #lochistory
)b
the output will be as below.
vehicle_id vehicle_name vehicle_id location date
1 car 1 india 2016-04-13 05:21:57.650
2 bus 1 india 2016-04-13 05:21:57.650
3 auto 1 india 2016-04-13 05:21:57.650
4 jeep 1 india 2016-04-13 05:21:57.650
Related
I AM USING MYSQL 8.0.
THIS IS MY DATA:
CREATE TABLE AA (
A int
);
insert into AA (A) values (1);
insert into AA (A) values (1);
insert into AA (A) values (2);
insert into AA (A) values (2);
insert into AA (A) values (1);
insert into AA (A) values (9);
insert into AA (A) values (NULL);
CREATE TABLE BB (
code int,
description varchar(30)
);
insert into BB (code, description) values (1, 'Male');
insert into BB (code, description) values (2, 'Female');
insert into BB (code, description) values (3, 'No Response');
THIS IS THE QUERY:
WITH cte AS (
SELECT MAX(CASE
WHEN a.A IS NULL THEN 9
WHEN b.code IS NULL THEN 8
ELSE a.A
END
) CODE,
CASE
WHEN a.A IS NULL THEN 'BLANK'
WHEN b.code IS NULL THEN 'NOT VALID'
ELSE b.description
END SEX,
COUNT(*) TOTAL,
ROUND(100.0 * COUNT(*) / SUM(COUNT(*)) OVER (), 2) PERCENT
FROM AA a LEFT JOIN BB b ON b.code = a.A
GROUP BY SEX
)
SELECT CODE, SEX, TOTAL, PERCENT,
SUM(TOTAL) OVER (ORDER BY CODE) CUMULATIVE,
ROUND(100.0 * SUM(TOTAL) OVER (ORDER BY CODE) / SUM(TOTAL) OVER (), 2) CUMPERCENT
FROM cte
UNION ALL
SELECT 0, 'TOTAL', COUNT(*), 100.00, 0, 0.00
FROM AA
ORDER BY CODE;
THIS IS THE OUTPUT:
CODE | SEX | TOTAL | PERCENT | CUMULATIVE | CUMPERCENT
0 TOTAL 7 100.00 0 0.00
1 MALE 3 42.86 3 42.86
2 FEMALE 2 28.57 5 71.43
8 NOT VALID 1 14.29 6 85.71
9 BLANK 1 14.29 7 100.00
EXPECTED OUTPUT:
CODE | SEX | TOTAL | PERCENT | CUMULATIVE | CUMPERCENT
0 TOTAL 7 100.00 0 0.00
1 Male 3 42.86 3 42.86
2 Female 2 28.57 5 71.43
3 No Response 0 0.00 5 71.43
8 NOT VALID 1 14.29 6 85.71
9 BLANK 1 14.29 7 100.00
This was just an update from my previous question. I just want to show in the output table all the category even if there are no data on it. In my expected output, the 'No Response' is '0' (or blank/NULL) since there is no value on it.
Thank you so much.
WITH
-- adjust table AA
cte1 AS (SELECT COALESCE(A, 8) A
FROM AA),
-- adjust table BB
cte2 AS (SELECT code, description
FROM BB
UNION ALL
SELECT 8, 'NOT VALID'
UNION ALL
SELECT 9, 'BLANK'),
-- join and calculate counts
cte3 AS (SELECT cte2.code CODE,
cte2.description SEX,
COUNT(cte1.A) TOTAL
FROM cte2
LEFT JOIN cte1 ON cte1.A = cte2.code
GROUP BY cte2.code, cte2.description)
-- calculate cumulative values
SELECT CODE,
SEX,
TOTAL,
ROUND(100.0 * TOTAL / SUM(TOTAL) OVER (), 2) PERCENT,
SUM(TOTAL) OVER (ORDER BY CODE) CUMULATIVE ,
ROUND(100.0 * SUM(TOTAL) OVER (ORDER BY CODE) / SUM(TOTAL) OVER (), 2) CUMUPERCENT
FROM cte3
UNION ALL
-- and add totals
SELECT 0,
'TOTAL',
(SELECT SUM(TOTAL) FROM cte3),
100,
0,
0
ORDER BY CODE
fiddle
If you add these 3 records to table BB:
insert into BB (code, description) values (8, 'NOT VALID');
insert into BB (code, description) values (9, 'BLANK');
and update AA like this:
UPDATE AA SET A=8 WHERE A IS NULL;
You could also do this:
WITH cte AS (
SELECT
COALESCE(b.code,0) as CODE,
b.description as SEX,
COUNT(a.A) TOTAL,
ROUND(100.0 * COUNT(a.A) / SUM(COUNT(a.A)) OVER (), 2) PERCENT
FROM AA a RIGHT JOIN BB b ON b.code = a.A
GROUP BY SEX
)
SELECT CODE, SEX, TOTAL, PERCENT,
SUM(TOTAL) OVER (ORDER BY CODE) CUMULATIVE,
ROUND(100.0 * SUM(TOTAL) OVER (ORDER BY CODE) / SUM(TOTAL) OVER (), 2) CUMPERCENT
FROM cte
UNION ALL
SELECT 0, 'TOTAL', COUNT(*), 100.00, 0, 0.00
FROM AA
ORDER BY CODE;
The biggest change is changing the LEFT JOIN to a RIGHT JOIN.
I have a table with hierarchical structure like this:
Create Table tbl1
(
AccountID NVARCHAR(100),
ID int,
ParentID int
);
INSERT INTO tbl1
VALUES ('11', 1, Null), ('12', 2, Null), ('13', 3, Null),
('11/11', 4, 1), ('11/12', 5, 1), ('11/111', 6, 1),
('11/11/001', 7, 4), ('11/11/002', 8, 4), ('12/111', 9, 2),
('12/112', 10, 2);
How to get all children of some nodes from tbl1 in tree structure, according to an other table (FilteringTbl) like this:
AccountID
---------
11/11
12
13
In other words I want to create a SQL query to get all children of nodes 11/11 and 12 and 13 from my first table (tbl1) in SQL Server 2008.
Main tables have more than 5000 records. (tbl1 5400 records and filteringtbl 1500 records)
Please help me. Thanks.
;with C
as (
select AccountID,
ID,
ParentID,
0 as [level]
from tbl1
where ID IN (SELECT ID FROM Filteringtbl)
union all
select I.AccountID,
I.ID,
I.ParentID,
C.[level] + 1 as [level]
from tbl1 as I
inner join C on
C.ID = I.ParentID
)
select *
from C
This is my tables
create table #vehicles (vehicle_id int, sVehicleName varchar(50))
create table #location_history ( vehicle_id int, location varchar(50), date datetime)
insert into #vehicles values
(1, 'MH 14 aa 1111'),
(2,'MH 12 bb 2222'),
(3,'MH 13 cc 3333'),
(4,'MH 42 dd 4444')
insert into #location_history values
( 1, 'aaa', getdate()),
( 1, 'bbb' , getdate()),
( 2, 'ccc', getdate()),
( 2, 'ddd', getdate()),
(3, 'eee', getdate()),
( 3, 'fff', getdate()),
( 4, 'ggg', getdate()),
( 4 ,'hhh', getdate())
This is query which I execute in SQL server.
select v.sVehicleName as VehicleNo, ll.Location
from #vehicles v outer APPLY
(select top 1 Location from #location_history where vehicle_id = v.vehicle_id
) ll
This is output in SQL server.
VehicleNO|Location
MH14aa1111 | aaa
MH12bb2222 | ccc
MH13cc3333 | eee
MH42dd4444 |ggg
I want to execute this in MySQL. and I want same output mentioned above.
First, the SQL Server query doesn't actually make sense, because you are using top without an order by.
Presumably, you intend something like this:
select v.sVehicleName as VehicleNo, ll.Location
from #vehicles v outer APPLY
(select top 1 Location
from #location_history
where vehicle_id = v.vehicle_id
order by ?? -- something to indicate ordering
) ll;
You need a method to get the latest record for each vehicle. Under normal circumstances, I think date would contain this information -- however, this is not true in your sample data.
Assuming that date really does contain unique values, then you can do:
select v.sVehicleName as VehicleNo, ll.Location
from vehicles v join
location_history lh
using (vehicle_id)
where lh.date = (select max(lh2.date)
from location_history lh2
where lh2.vehicle_id = lh.vehicle_id
);
Otherwise, you can do what you want using a correlated subquery. However, this will return an arbitrary matching value on the most recent date:
select v.sVehicleName as VehicleNo,
(select ll.Location
from location_history lh2
where lh2.vehicle_id = lh.vehicle_id
order by date desc
limit 1
) as location
from vehicles v ;
i have create a table and insert some dummy data with this query:
CREATE TABLE transaction (
idtransaction INT NOT NULL AUTO_INCREMENT,
idproduct INT NOT NULL,
quantity INT NOT NULL,
PRIMARY KEY (idtransaction));
INSERT INTO transaction (idproduct, quantity) VALUES
(1, 100),
(1, 200),
(2, 120),
(3, 300),
(2, 200),
(2, 200),
(1, 300);
and i want to get a table result like this:
|idtransaction| idproduct | quantity | saldo
1 1 100 100
2 1 100 200
3 2 120 120
4 3 300 300
5 2 200 320
6 2 200 520
7 1 300 500
i have create a query like this:
SELECT idtransaction,
idproduct,
quantity,
(#saldo := #saldo + quantity) as saldo
FROM transaction
LEFT JOIN
(select #saldo :=0) as s on 1=1;
but, the result of saldo history is calculate for all idproduct.
how to get 'saldo' history for every idproduct?
You need to order the data by idproduct, and then reset #saldo whenever idproduct changes.
If you want the final result ordered by idtransaction, put the query with the running total in a sub-query, and apply the new order to that.
SELECT *
FROM (
SELECT idtransaction, idproduct, quantity,
#saldo := IF(idproduct = #lastproduct, #saldo + quantity, quantity) AS saldo,
#lastproduct := idproduct
FROM (SELECT *
FROM transaction
ORDER BY idproduct, idtransaction) AS t
CROSS JOIN (SELECT #saldo := 0, #lastproduct = NULL) AS vars) AS x
ORDER BY idtransaction
DEMO
I'm somewhat new to SQL.
There is a chart like below picture and it was saved into table with id , pid (parent id) , level .
How can I find all child of node in a special level?
For example: All child of c in level 4 = F , G , H
Could you help me, please?
It solved by following code:
;WITH r as (
SELECT *
FROM Chart
WHERE ParentID = 3
UNION ALL
SELECT d.*
FROM Chart d
INNER JOIN r
ON d.ParentID = r.KID
)
SELECT *
FROM r
where KLevel = 4
It is good to have additional table with node relations. E.g. table successors with columns pid and sid (successor id). There you have rows with pid=3 (C) and sid=4,5,6,7,8. Then you run simple query:
SELECT s.sid
FROM table t JOIN successor s ON t.id=s.pid JOIN table t2 ON t2.id=s.sid
WHERE t.id=3 AND t2.level=4;
You can use a recursive query which will look for child rows.
Then you only have to SELECT value with the requiered level.
Query:
with cte(id) as(
SELECT id FROM #data WHERE name = #parent
UNION ALL
SELECT d.id FROM #data d
INNER JOIN cte c ON c.id = d.pid
WHERE d.[level] <= #level
)
SELECT d.name, d.id, d.pid, d.level FROM #data d
INNER JOIN cte c ON c.id = d.id
WHERE d.[level] = #level
Output:
name id pid level
g 7 5 4
h 8 5 4
f 6 4 4
Your data:
Declare #parent char(1) = 'C';
Declare #level int = 4;
Declare #data table(id int, pid int, name char(1), [level] int);
INSERT INTO #data(id, pid, name, [level]) values
(1, 0, 'a', 1)
, (2, 1, 'b', 2)
, (3, 1, 'c', 2)
, (4, 3, 'd', 3)
, (5, 3, 'e', 3)
, (6, 4, 'f', 4)
, (7, 5, 'g', 4)
, (8, 5, 'h', 4)
;