below is database and table details.
database name - mis_v1
table 1 name - trips
table 2 name - client
i tried below queries
Query 1
select cl.client_name CLIENT
, count(t.trip_type) TRIPS
, count(distinct t.vehicle_reg_no) VEHICLES
from mis_v1.trips t
JOIN mis_v1.client cl
ON cl.id = t.client_id
group
by cl.client_name;
Query 1 result
CLIENT TRIPS VEHICLES
anz-ABlr 118 16
citrix-CBlr 159 15
dxc-DBlr 26 5
Eps-Blr 116 24
goc-GocHyd 191 10
Unisys-BLR 192 55
Wipro-Ncr 86 33
Wipro-Pnq 10 5
Query 2
select cl.client_name CLIENT
, count(t.trip_delay_reason) LATE_TRIPS
FROM mis_v1.trips t
JOIN mis_v1.client cl
ON cl.id = t.client_id
where t.trip_delay_reason = "DRIVER"
group
by cl.client_name;
Query 2 result
CLIENT LATE_TRIPS
anz-ABlr 53
citrix-CBlr 25
dxc-DBlr 1
Wipro-Ncr 1
goc-GocHyd 17
I need result as below
CLIENT TRIPS VEHICLES LATE_TRIPS
anz-ABlr 118 16 53
citrix-CBlr 159 15 25
dxc-DBlr 26 5 1
Eps-Blr 116 24 -
goc-GocHyd 191 10 17
Unisys-BLR 192 55 -
Wipro-Ncr 86 33 1
Wipro-Pnq 10 5 -
Kindly give me solution.Thanks in advance
If I understood you correctly, you need something like this:
select cl.client_name CLIENT
, count(t.trip_type) TRIPS
, count(distinct t.vehicle_reg_no) VEHICLES
, coalesce(cast(count(case when t.trip_delay_reason = "DRIVER" then 1 else null end) as char), '-') LATE_TRIPS
from mis_v1.trips t
JOIN mis_v1.client cl
ON cl.id = t.client_id
group
by cl.client_name;
So, please read more about COUNT aggreagate function and probably CASE operator
Related
Note that object_id's 18,10 and 21 are associated to the cart_id 3 once. I wanna know whether the combination occurs again in another cart_id and how many times does that occurs over all the rows existent. I expect two columns as a resultset "combination" and "combination_occurrence_count"
It is quite complicated task to check all possible combinations as it is too many of them.
However, if you simplify your requirements a bit, you can get something useful.
Lets start with finding all combinations of two items. At the beginning you can try the following query:
SELECT
c1.cart_id AS cart1_id
, c1.object_id AS object1_id
, c2.object_id AS object2_id
, cx1.cart_id AS cartX_id
, cx1.object_id AS objectX1_id
, cx2.object_id AS objectX2_id
FROM
cart_item AS c1
INNER JOIN cart_item AS c2 ON (
c2.cart_id = c1.cart_id
AND c2.object_id > c1.object_id
)
INNER JOIN cart_item AS cx1 ON (
cx1.cart_id > c1.cart_id
AND cx1.object_id = c1.object_id
)
INNER JOIN cart_item AS cx2 ON (
cx2.cart_id = cx1.cart_id
AND cx2.object_id = c2.object_id
)
ORDER BY
c1.cart_id
, c1.object_id
, c2.object_id
, cx1.cart_id
, cx1.object_id
, cx2.object_id
There are two ideas behind the query:
Get all possible combinations of two object ids that are exist in
carts. Carts with only one item will be excluded. The only existing
combinations would be analyzed (instead of all possible combinations). [c1 & c2]
Find other carts that have the same object ids combinations [cx1 & cx2]
The results would be something like this:
cart1_id object1_id object2_id cartX_id objectX1_id objectX2_id
3 10 18 30 10 18
3 10 18 31 10 18
3 10 21 30 10 21
3 18 21 30 18 21
30 10 18 31 10 18
Then you can group these results to get "the most popular" pairs:
SELECT
cx1.object_id AS object1_id
, cx2.object_id AS object2_id
, 1 + COUNT(DISTINCT cx1.cart_id) AS cnt
FROM
cart_item AS c1
INNER JOIN cart_item AS c2 ON (
c2.cart_id = c1.cart_id
AND c2.object_id > c1.object_id
)
INNER JOIN cart_item AS cx1 ON (
cx1.cart_id > c1.cart_id
AND cx1.object_id = c1.object_id
)
INNER JOIN cart_item AS cx2 ON (
cx2.cart_id = cx1.cart_id
AND cx2.object_id = c2.object_id
)
GROUP BY
cx1.object_id
, cx2.object_id
ORDER BY
cnt DESC
LIMIT
20
Results:
object1_id object2_id cnt
10 18 3
10 21 2
18 21 2
So pair 10 + 18 is the most popular and are exist in 3 carts.
Pairs 10 + 21 and 18 + 21 are in 2 different carts.
You can continue and do something like this for 3-objects combinations.
P.S. I used the following data set (added a few rows to your data to get a bit more interesting results):
id cart_id object_id
10 2 24
9 3 10
3 3 18
19 3 21
12 4 24
1 7 30
5 9 24
2 11 10
20 14 12
14 14 18
8 14 27
13 15 11
7 16 9
18 16 13
15 20 11
6 21 6
4 23 5
17 23 6
16 25 16
11 29 11
23 30 1
21 30 10
22 30 18
24 30 21
25 31 10
26 31 18
P.P.S. I have not spent too much time on this so it is possible that I missed something in queries. However, I hope you understand the general idea.
The following returns the list of carts with all three objects:
select cart_id
from t
where object_id in (18, 10, 21)
group by cart_id
having count(distinct cart_id) = 3;
select group_concat(`app_item`.`object_id`) as `combination`
from `app_item`
group by `app_item`.`cart_id`
The query return a "combination" resultset as I was looking for:
Since I cannot group again using the "combination" and then make a count of occurrences for each combination and then get the "combination_occurrence_count" it contains, I am now doing this through a method in the application as following
and now I can display an array as key/pair like "combination" => "occurrence count" as following
This question already has answers here:
What's the most efficient way to select the last n rows in a table without changing the table's structure?
(8 answers)
Closed 4 years ago.
I want to make a query that retrieve data from two table i.e one is purchase and another is issue.
both tables have same fields i.e icode,qty,rate,purdate and issuedate.
query of purchase is:-SELECT Dry_Purchase.Icode, Sum(Dry_Purchase.Qty) AS SumOfQty, Dry_Purchase.Rate
FROM Dry_Purchase
WHERE (((Dry_Purchase.PurDate) Between DateSerial(Year(Date()),(Month(Date())-1),21) And DateSerial(Year(Date()),Month(Date()),20)))
GROUP BY Dry_Purchase.Icode, Dry_Purchase.Rate;
output of purchase query is:
Icode SumOfQty Rate
11 10 13.5
11 39.5 14
19 75 79.75
19 22 80
21 54 87.45
23 15 218
24 10.5 650
8 79 33.25
8 13 34
query of issue is :- SELECT Dry_Expense.Icode, Sum(Dry_Expense.Qty) AS SumOfQty, Dry_Expense.Rate
FROM Dry_Expense
WHERE (((Dry_Expense.ExpDate) Between DateSerial(Year(Date()),(Month(Date())-1),21) And DateSerial(Year(Date()),Month(Date()),20)))
GROUP BY Dry_Expense.Icode, Dry_Expense.Rate;
output of this query is
Icode SumOfQty Rate
11 11.55 13
11 8.55 13.5
11 10.8 14
19 2.35 80
21 54 87.45
8 15.9 33.25
after combining above both query the output should like this
rptdate icode opening recd issued closingbal rate
19/09/18 11 0 10 8.550 1.450 13.50
19/09/18 11 0 39.5 10.800 28.700 14.00
19/09/18 19 0 75 0.000 75 79.75
19/09/18 19 0 22 2.350 72.650 80.00
19/09/18 21 0 54 54 0 87.45
19/09/18 23 0 15 0 15 218.00
19/09/18 24 0 10.5 0 10.500 650.00
19/09/18 8 0 79.0 15.900 63.100 33.25
19/09/18 8 0 13.0 0 13.000 34.00
19/09/18 8 11.550 0 11.550 0 13.00
please help me how to make query for this output
i am trying this query
SELECT A.icode,A.qty,A.rate,A.recd as recd,B.Issued as Issue
FROM (SELECT icode,rate,purdate,SUM(Abs(qty)) AS recd
FROM Dry_Purchase GROUP BY icde,rate ) A,
(SELECT icode,rate,expdate,(SUM(Abs(qty)) AS Issue
FROM Dry_Expense GROUP BY icode,rate) B
WHERE A.icode=B.icode AND A.rate=B.rate AND
(A.purdate Between DateSerial((Year(Date()),(Month(Date())-1),21)) And DateSerial(Year(Date()),Month(Date()),20))
AND B.expdate Between DateSerial((Year(Date()),(Month(Date())-1),21) And DateSerial(Year(Date()),Month(Date()),20));
please help me
Use a sub-select to locate the minimum date, then join to the to get the row matching that date.
SELECT
a.`Purdate` AS a.`Date1`, a.`Qty`, a.`Rate`
FROM `TableName` a
JOIN (SELECT MIN(`PurDate`) as `minDate`
FROM `TableName`
WHERE `Icode` = '1') b
ON b.`minDate` = a.`PurDate`
WHERE a.`Icode` = '1'
Since you don't need grouping you can just order by the date column and get the first two rows.
SELECT PurDate, Qty, Rate FROM TableName WHERE Icode = '1' ORDER BY PurDate LIMIT 2
use corelated sub query and union
select A.* from
(
select * from tablename t1 #1st min date will return
where t1.purdate in
(select min(purdate) from
tablename t2 where t2.icode=t1.icode
)
union
select t1.* from tablename t1 inner join
(SELECT
Icode
, Purdate
FROM (
SELECT
#row_num :=IF(#prev_value=Icode,#row_num+1,1) AS rn
, mp.Icode
, mp.Purdate
, #prev_value := Icode
FROM tablename mp
CROSS JOIN (SELECT #row_num :=1, #prev_value :='') vars
ORDER BY
mp.Icode
, mp.Purdate DESC
) d
WHERE rn = 2
) t2
on t1.Icode=t2.Icode and t1.Purdate=t2.Purdate
) as A where A.Icode in (......)
Struggling with some sql, would appreciate some guidance.
Have two tables logs and sense
logs –
assetid ts nodeid status
1 2017-10-26 14:00:10 73 240
2 2017-10-26 14:00:06 21 160
3 2017-10-26 14:00:04 18 230
4 2017-10-26 14:00:02 19 400
5 2017-10-26 14:00:00 21 190
1 2017-10-26 13:20:08 18 20
2 2017-10-26 13:06:10 20 160
3 2017-10-26 13:03:04 17 230
sense –
status value
20 5
160 37
190 39
230 56
240 58
400 90
Trying to find the correct syntax to only show the latest record (in datetime) of each assetid and then show the corresponding value from the sense table (based on the matching status in both tables) to produce –
assetid ts nodeid status value
1 2017-10-26 14:00:10 73 240 58
2 2017-10-26 14:00:06 21 160 37
3 2017-10-26 14:00:04 18 230 56
4 2017-10-26 14:00:02 19 400 90
5 2017-10-26 14:00:00 21 190 39
Have tried –
Select assetid, ts, nodeid, status, value
From
logs
Join sense X on X.status = logs.status
Group by assetid
Order by ts DESC
But this only outputs 1 row (instead of 5)
assetid ts nodeid status value
1 2017-10-26 14:00:10 73 240 58
Removing
Join sense X on X.status = logs.status
of course outputs all records but that is not required.
Thoughts appreciated.
Regards
Active
Actually your query is returning 5 rows, 1 for each id. But it won't return rows with latest ts for each id. You can verify this by clicking on the link for demo. You can compare results of both queries.
To achieve this task,following query will help you:
Select l.assetid, l.ts, logs.nodeid, X.status, X.value
From
logs
inner Join sense X on X.status = logs.status
inner join (select assetid, max(ts) as ts from logs group by assetid) l
on l.assetid = logs.assetid and logs.ts = l.ts
Group by l.assetid
Order by l.ts DESC;
Click here for Demo
EDIT:
If dataype of ts is string then replace max(ts) in above query with:
max(str_to_date(ts,'%d%m%y'))
Feel free to ask any doubts.
Hope it helps!
Try this
Select a1.assetid, MAX(a1.ts), a1.nodeid, a1.status, X.value
From
logs a1
inner join sense X on X.status = a1.status
Group by assetid, a1.nodeid, a1.status, X.value
Order by ts DESC
Use GROUP BY to find minimum for each assetid and then JOIN with the logs and sense
Select *
FROM logs l
JOIN sense s ON s.status = l.status
JOIN
(
Select assetid, max(ts) maxts
From logs
Group by assetid
) t ON t.assetid = l.assetid and l.ts = t.maxts
demo
On MY SQL 8.0.2
WITH CTE as
(
Select A.assetid, A.ts, A.nodeid, A.status, B.value, row_number() over(PARTITION BY A.assetid ORDER BY A.ts DESC) AS rn
from logs as A
inner join sense B ON A.status=B.status
)
SELECT *
FROM CTE
WHERE rn='1';
I am working in access 2010 I have a table which has the following format:
ID BOORP BEGIN_DIEPTE EIND_DIEPTE TEXTUUR1
1 148000 0 10 ZK
2 148000 20 60 ZK
3 148000 60 80 MK
4 148000 80 110 MK
5 148000 110 130 ZK
6 148000 130 160 -
7 148000 160 220 ZZL
8 148000 220 250 -
9 148000 250 300 MK
10 148001 0 20 ZK
11 148001 20 40 -
12 148001 40 210 ZZL
13 148001 210 310 ZZL
What i want is to join certain rows which have the same texture under the following conditions:
1) rows must have the same BOORP in order to be merged
2) only consecutive rows may be merged
The result should look like this:
ID BOORP BEGIN_DIEPTE EIND_DIEPTE TEXTUUR1
1 148000 0 60 ZK
3 148000 60 110 MK
5 148000 110 130 ZK
6 148000 130 160 -
7 148000 160 220 ZZL
8 148000 220 250 -
9 148000 250 300 MK
10 148001 0 20 MK
11 148001 20 40 -
12 148001 40 310 ZZL
It is especially the 2nd condition i'm having problem with.
Any suggestions?
That's quite a complex task as an SQL-only solution.
If you want to do it in one query, you can use the following solution (tested on your sample data):
SELECT e.ID, e.BOORP, e.BEGIN_DIEPTE, e.EINDDIEPTE As EIND_DIEPTE, e.TEXTUUR1
FROM
(
SELECT a.ID, a.BOORP, a.BEGIN_DIEPTE, IIF(b.ID Is Null, a.EIND_DIEPTE, b.EIND_DIEPTE) AS EINDDIEPTE, a.TEXTUUR1, b.ID As IDJoined
FROM TestTable a
LEFT JOIN
(
SELECT c.*, (SELECT Max(d.ID) FROM TestTable d WHERE d.ID < c.ID) As PreviousID
FROM TestTable c
) As b
ON b.PreviousID = a.ID AND b.BOORP = a.BOORP AND a.TEXTUUR1 = b.TEXTUUR1
) AS e
WHERE e.ID NOT IN (
SELECT b.ID
FROM TestTable a
INNER JOIN
(
SELECT c.*, (SELECT Max(d.ID) FROM TestTable d WHERE d.ID < c.ID) As PreviousID
FROM TestTable c
) As b
ON b.PreviousID = a.ID AND b.BOORP = a.BOORP AND a.TEXTUUR1 = b.TEXTUUR1
)
It's quite a lot of subqueries, and a bit too much to explain in depth. Simply put, the most inner subquery (query b) LEFT JOINs on equal BOORP and TEXTUUR1 and where the ID is the previous ID, then the outer subquery (query e) takes the result, and removes all the entries that have been joined with another entry.
Note that this joins 2 entries together, not more than that. If you want to join more than 2 entries together, you can just run a similar query on the result of this one.
I'm stuck with Mysql... I'm sure this question have been asked hundreds of times but without any keyword. I've 2 tables and a view:
tbl_user_measure
measure_cat userid amount
------------------------------
7 1 78
5 1 96
4 1 78
tbl_itemcat_measure
measure_cat item_cat
----------------------
7 1
5 1
4 1
vw_allitems
measure_cat min max item_cat itemid
---------------------------------------------------
7 76 81 1 1
5 97 100 1 1
4 79 81 1 1
7 76 81 1 11
5 95 97.5 1 11
4 76 79 1 11
4 33 12 2 5
What I'm looking for is the item(s) whose min and max values match in all measure_cat's of the specific item_cat the users values (max > tbl_user_measure.amount > min).
My approach was
SELECT distinct
v.itemid,
v.measure_cat_id,
v.min,
v.max
FROM
vw_allitems v, tbl_user_measure um, tbl_user u
where
um.tbl_measure_category_id = v.measure_cat_id and
(um.amount >= v.min and um.amount <= v.max) and
v.productid = 1
This resultes in:
itemid measure_cat_id min max
---------------------------------------------------
1 7 76 81
7 7 76 81
10 7 76 81
11 7 76 81
11 4 76 79
11 5 95 9
What I need is just the itemid '11' because its values fit in all categories.
Looks like you're almost there. Your query returns all matching rows; change it so that it returns the itemid and the count, grouped by itemid. All that's left is just to return those items where the count is equal to the number of rows that user has in the first table.
UPDATE: This should do what you need:
SELECT x.itemid, x.measure_cat, x.min, x.max
FROM
(SELECT vw.itemid i, u.userid u, count(*) mc
FROM vw_allitems vw
JOIN tbl_user_measure u ON vw.measure_cat=u.measure_cat
WHERE u.amount>=vw.min and u.amount<=vw.max
GROUP BY vw.itemid, u.userid) match_counts
JOIN
(SELECT userid u, count(*) uc
FROM tbl_user_measure
GROUP BY userid) user_counts
ON match_counts.u = user_counts.u
AND match_counts.mc=user_counts.uc
JOIN
vw_allitems x
ON match_counts.i = x.itemid
WHERE match_counts.u=1
Quick walkthrough. The first subquery takes every combination of user and item, and counts the number of matches. The second subquery counts how many entries that user has in tbl_user_measure. The join selects just those users and items where the match count equals the total count for that user (i.e. all the user's entries match), then finally we join it to the original data to return the original rows from vw_allitems and select just the user we are interested in.
Try this query:
SELECT v.itemid,
v.measure_cat_id,
v.min,
v.max
FROM vw_allitems as v,
INNER JOIN tbl_user_measure as um
ON um.measure_cat = v.measure_cat and um.amount >= v.min and um.amount <= v.max
INNER JOIN tbl_itemcat_measure as im
ON im.item_cat=um.item_cat