Subquery for max ID numbers - sql

I have a query that I am trying to filter for a report. Each addressID can have multiple jobs and each job can have multiple elements to it.
Basically I am trying to get the maximum jobID for each addressID, but I want to get each element of the job.
The current Query results are:
+-----------+-------+--------+
| AddressID | JobID | Cost |
+-----------+-------+--------+
| 326 | 328 | £52.50 |
| 327 | 329 | £55.13 |
| 328 | 330 | £57.88 |
| 329 | 331 | £60.78 |
| 329 | 331 | £63.81 |
| 330 | 332 | £67.00 |
| 330 | 332 | £70.36 |
| 330 | 332 | £73.87 |
| 330 | 332 | £77.57 |
| 330 | 333 | £57.75 |
| 330 | 333 | £60.64 |
| 330 | 333 | £63.67 |
| 330 | 333 | £66.85 |
| 331 | 334 | £70.20 |
| 331 | 334 | £73.71 |
| 331 | 335 | £77.39 |
| 331 | 336 | £81.26 |
| 331 | 336 | £85.32 |
| 331 | 336 | £89.59 |
+-----------+-------+--------+
And I am trying to get:
+-----------+-------+--------+
| AddressID | JobID | Cost |
+-----------+-------+--------+
| 326 | 328 | £52.50 |
| 327 | 329 | £55.13 |
| 328 | 330 | £57.88 |
| 329 | 331 | £60.78 |
| 329 | 331 | £63.81 |
| 330 | 333 | £57.75 |
| 330 | 333 | £60.64 |
| 330 | 333 | £63.67 |
| 330 | 333 | £66.85 |
| 331 | 336 | £81.26 |
| 331 | 336 | £85.32 |
| 331 | 336 | £89.59 |
+-----------+-------+--------+
I had been looking at SELECT TOP 1 to isolate the MAX JobID, but ended up limiting the query to just 1 entry.
Currently tweaking this subquery, but still not sure I'm on the right track:
(SELECT Max(vusearch.JobID) FROM vuSearch AS T WHERE PAID = vuSearch.AddressID GROUP BY AddressID)
Can anyone advise?

Here is one method:
select v.*
from vusearch as v
where v.JobId = (select max(v2.JobId)
from vusearch as v2
where v2.AddressId = v.AddressId
);

Managed to get it fixed - I probably hadn't provided enough information as I was trying to keep my explanation simple.
Many thanks for your help Gordon
((vuSearch.PDID) IN ( (SELECT Max(v2.PDID) FROM vuSearch AS v2 GROUP BY v2.PAID)))

Related

Average by day using timestamp

I have the following mariadb table. The data is added 3 times per day. I am looking to write a SQL query that would give me the average amount for the day. This way I can say on May 13 'serender' averaged x amt, 'shilta' averaged x amt and 'snowq' averaged x amt. On May 14th the averages were... and so on for each date.
key | timestamp | card | amt |
-------------------------------------------
| 126 | 1620837006 | serender | 8040 |
| 127 | 1620837006 | shilta | 752 |
| 128 | 1620837006 | snowq | 308 |
| 132 | 1620862207 | serender | 846 |
| 133 | 1620862207 | shilta | 803 |
| 134 | 1620862207 | snowq | 759 |
| 139 | 1620894616 | serender | 845 |
| 140 | 1620894616 | shilta | 805 |
| 141 | 1620894616 | snowq | 759 |
| 146 | 1620923404 | serender | 869 |
| 147 | 1620923404 | shilta | 804 |
| 148 | 1620923404 | snowq | 759 |
| 153 | 1620948607 | serender | 755 |
| 154 | 1620948607 | shilta | 650 |
| 155 | 1620948607 | snowq | 530 |
If you want to see the date then convert it from a Unix timestamp to a date:
select date(from_unixtime(timstamp)) as dte, card, avg(amt)
from t
group by dte, card;

SQL: FIter rows with specyfic pattern

I'm a bit new in sql.
I have the following table:
+-----+---------+------------------------+
| ID | ID_TEST | FILE_PATH |
+-----+---------+------------------------+
| 575 | 3 | Landscapes_001_h_A.jpg |
| 576 | 3 | Landscapes_001_h_B.jpg |
| 577 | 3 | Landscapes_001_h_C.jpg |
| 578 | 3 | Landscapes_001_h_D.jpg |
| 579 | 3 | Landscapes_001_h_E.jpg |
| 580 | 3 | Landscapes_002_h_A.jpg |
| 581 | 3 | Landscapes_002_h_B.jpg |
| 582 | 3 | Landscapes_002_h_C.jpg |
| 583 | 3 | Landscapes_002_h_D.jpg |
| 584 | 3 | Landscapes_002_h_E.jpg |
+-----+---------+------------------------+
The pattern for picture is Landscapes_XXX_h_Y.jpg
where
XXX is number from 1 to 185 and Y is quality version from A to E
I wanna select each image name with different quality.
The output should be
+-----+---------+------------------------+
| ID | ID_TEST | FILE_PATH |
+-----+---------+------------------------+
| 575 | 3 | Landscapes_001_h_A.jpg |
| 576 | 3 | Landscapes_002_h_E.jpg |
| 577 | 3 | Landscapes_003_h_C.jpg |
| 578 | 3 | Landscapes_004_h_B.jpg |
| 579 | 3 | Landscapes_005_h_D.jpg |
| 580 | 3 | Landscapes_006_h_A.jpg |
| 581 | 3 | Landscapes_007_h_E.jpg |
| 582 | 3 | Landscapes_008_h_C.jpg |
| 583 | 3 | Landscapes_009_h_B.jpg |
| 584 | 3 | Landscapes_010_h_E.jpg |
+-----+---------+------------------------+
but of course for 185 elements.
I'm using 5.5.60-MariaDB.
How to write SELECT statement? Using REGEXP?

Getting two columns one containing and one not containing a grouped value

My data looks like this -
+-----------+-----------+-----------+----------+
| FLIGHT_NO | FL_DATE | SERIAL_NO | PILOT_NO |
+-----------+-----------+-----------+----------+
| 501 | 15-OCT-19 | 456710 | 345 |
| 521 | 16-OCT-19 | 562911 | 345 |
| 534 | 17-OCT-19 | 877694 | 345 |
| 577 | 17-OCT-19 | 338157 | 345 |
| 501 | 14-OCT-19 | 921225 | 346 |
| 534 | 15-OCT-19 | 877694 | 346 |
| 534 | 14-OCT-19 | 338157 | 347 |
| 590 | 16-OCT-19 | 650012 | 347 |
| 531 | 14-OCT-19 | 562911 | 348 |
| 531 | 15-OCT-19 | 562911 | 348 |
| 501 | 16-OCT-19 | 220989 | 349 |
| 521 | 18-OCT-19 | 650012 | 349 |
| 590 | 14-OCT-19 | 562911 | 351 |
| 577 | 18-OCT-19 | 877694 | 351 |
| 590 | 18-OCT-19 | 456710 | 346 |
+-----------+-----------+-----------+----------+
My aim is to return the total number of flights flying and not flying on 18-oct-19.
I'm doing it with dual but that doesn't seem to be the correct/best method.
Can anyone help me do it the correct way?
SELECT
(SELECT COUNT(FLIGHT_NO) NO_FLY FROM schd_flight WHERE fl_date = '18-OCT-19') AS FLY,
(SELECT COUNT(FLIGHT_NO) NO_FLY FROM schd_flight WHERE fl_date <> '18-OCT-19') AS NO_FLY
FROM dual;
My output -
+-----+--------+
| fly | no_fly |
+-----+--------+
| 3 | 12 |
+-----+--------+
Simply use sum with case statement
Select
sum(case when fl_date = '18-OCT-19' then 1 end) fly,
sum(case when fl_date <> '18-OCT-19' then 1 end) no_fly
From schd_flight;
Cheers!!
I think the second query is not necessary, no_fly = total - fly.
So I came up with my solution, may improve the query time :
SELECT sub.FLY as FLY, (SELECT count(*) from schd_flight) - sub.FLY as NO_FLY
FROM (
SELECT COUNT(CASE when fl_date = '18-OCT-19' then 1 end) AS FLY
from schd_flight
) sub;
Not tested yet though.

Create Set of IDs based on Varying ID Ranges

I have a collection of tables that have missing document ID ranges. The Start Range is the beginning ID, the End Range is the ending ID, and the Missing is the number of rows within that range that are missing (includes the beginning and end ID within its count). I was wondering how I can go about parsing into a new table the individual IDs as opposed to the actual range based on the Missing column.
This is how the data is presented:
+-------------+-----------+---------+-----------+
| Start Range | End Range | Missing | Date |
+-------------+-----------+---------+-----------+
| 184 | 186 | 3 | 1/9/1979 |
| 204 | 207 | 4 | 1/9/1979 |
| 209 | 212 | 4 | 1/9/1979 |
| 223 | 224 | 2 | 1/9/1979 |
| 240 | 241 | 2 | 1/10/1979 |
| 243 | 243 | 1 | 1/10/1979 |
| 248 | 249 | 2 | 1/10/1979 |
| 261 | 265 | 5 | 1/11/1979 |
+-------------+-----------+---------+-----------+
I am looking to acheive output as such:
+-----+-----------+
| ID | Date |
+-----+-----------+
| 184 | 1/9/1979 |
| 185 | 1/9/1979 |
| 186 | 1/9/1979 |
| 204 | 1/9/1979 |
| 205 | 1/9/1979 |
| 206 | 1/9/1979 |
| 207 | 1/9/1979 |
| 209 | 1/9/1979 |
| 210 | 1/9/1979 |
| 211 | 1/9/1979 |
| 212 | 1/9/1979 |
| 223 | 1/9/1979 |
| 224 | 1/9/1979 |
| 240 | 1/10/1979 |
| 241 | 1/10/1979 |
| 243 | 1/10/1979 |
| 248 | 1/10/1979 |
| 249 | 1/10/1979 |
| 261 | 1/11/1979 |
| 262 | 1/11/1979 |
| 263 | 1/11/1979 |
| 264 | 1/11/1979 |
| 265 | 1/11/1979 |
+-----+-----------+
What would be the best method to achieve this? Thanks for the assistance.
I use a UDF to generate ranges, but a numbers table or tally table would do the trick as well
Declare #Table table (StartRange int,EndRange int,Date Date)
Insert into #Table values
(184,186,'1979-01-09'),
(204,207,'1979-01-09')
Select B.ID
,A.Date
From #Table A
Join (Select ID=cast(RetVal as int) from [dbo].[udf-Create-Range-Number](1,9999,1)) B
on B.ID between A.StartRange and A.EndRange
Order by B.ID,Date
Returns
ID Date
184 1979-01-09
185 1979-01-09
186 1979-01-09
204 1979-01-09
205 1979-01-09
206 1979-01-09
207 1979-01-09
The UDF
CREATE FUNCTION [dbo].[udf-Create-Range-Number] (#R1 money,#R2 money,#Incr money)
-- Syntax Select * from [dbo].[udf-Create-Range-Number](0,100,2)
Returns
#ReturnVal Table (RetVal money)
As
Begin
With NumbTable as (
Select NumbFrom = #R1
union all
Select nf.NumbFrom + #Incr
From NumbTable nf
Where nf.NumbFrom < #R2
)
Insert into #ReturnVal(RetVal)
Select NumbFrom from NumbTable Option (maxrecursion 32767)
Return
End
Build a tally table or CTE.
tally table
Which is just a single column of incrementing integers n
Select tally.n as Id, missingRange.date
from tally
inner join missingRange
On tally.n >= beginRange
And tally.n <= endRange

How to SUM from MySQL for every n record

I have a following result from query:
+---------------+------+------+------+------+------+------+------+-------+
| order_main_id | S36 | S37 | S38 | S39 | S40 | S41 | S42 | total |
+---------------+------+------+------+------+------+------+------+-------+
| 26 | 127 | 247 | 335 | 333 | 223 | 111 | 18 | 1394 |
| 26 | 323 | 606 | 772 | 765 | 573 | 312 | 154 | 3505 |
| 38 | 25 | 35 | 35 | 35 | 20 | NULL | NULL | 150 |
| 38 | 25 | 35 | 35 | 35 | 20 | NULL | NULL | 150 |
| 39 | 65 | 86 | 86 | 42 | 21 | NULL | NULL | 300 |
| 39 | 42 | 58 | 58 | 28 | 14 | NULL | NULL | 200 |
| 35 | 11 | 20 | 21 | 18 | 9 | 2 | NULL | 81 |
| 35 | 10 | 25 | 30 | 23 | 12 | 1 | NULL | 101 |
+---------------+------+------+------+------+------+------+------+-------+
I would like to insert a SUM before enter different order_main_id, it would be like this result:
+---------------+------+------+------+------+------+------+------+-------+
| order_main_id | S36 | S37 | S38 | S39 | S40 | S41 | S42 | total |
+---------------+------+------+------+------+------+------+------+-------+
| 26 | 127 | 247 | 335 | 333 | 223 | 111 | 18 | 1394 |
| 26 | 323 | 606 | 772 | 765 | 573 | 312 | 154 | 3505 |
| | 450 | 853 | 1107 | 1098 | 796 | 423 | 172 | 4899 |
| 38 | 25 | 35 | 35 | 35 | 20 | NULL | NULL | 150 |
| 38 | 25 | 35 | 35 | 35 | 20 | NULL | NULL | 150 |
| | 50 | 70 | 70 | 70 | 40 | NULL | NULL | 300 |
| 39 | 65 | 86 | 86 | 42 | 21 | NULL | NULL | 300 |
| 39 | 42 | 58 | 58 | 28 | 14 | NULL | NULL | 200 |
| | 107 | 144 | 144 | 70 | 35 | NULL | NULL | 500 |
| 35 | 11 | 20 | 21 | 18 | 9 | 2 | NULL | 81 |
| 35 | 10 | 25 | 30 | 23 | 12 | 1 | NULL | 101 |
| | 21 | 45 | 51 | 41 | 21 | 3 | NULL | 182 |
+---------------+------+------+------+------+------+------+------+-------+
How to make this possible ?
You'll need to write a second Query which makes use of GROUP BY order_main_id.
Something like:
SELECT sum(S41+...) FROM yourTable GROUP BY orderMainId
K
You can actually do this in one query, but with a union all (really two queries, but the result sets are combined to make one awesome result set):
select
order_main_id,
S36,
S37,
S38,
S39,
S40,
S41,
S42,
S36 + S37 + S38 + S39 + S40 + S41 + S42 as total,
'Detail' as rowtype
from
tblA
union all
select
order_main_id,
sum(S36),
sum(S37),
sum(S38),
sum(S39),
sum(S40),
sum(S41),
sum(S42),
sum(S36 + S37 + S38 + S39 + S40 + S41 + S42),
'Summary' as rowtype
from
tblA
group by
order_main_id
order by
order_main_id, RowType
Remember that the order by affects the entirety of the union all, not just the last query. So, your resultset would look like this:
+---------------+------+------+------+------+------+------+------+-------+---------+
| order_main_id | S36 | S37 | S38 | S39 | S40 | S41 | S42 | total | rowtype |
+---------------+------+------+------+------+------+------+------+-------+---------+
| 26 | 127 | 247 | 335 | 333 | 223 | 111 | 18 | 1394 | Detail |
| 26 | 323 | 606 | 772 | 765 | 573 | 312 | 154 | 3505 | Detail |
| 26 | 450 | 853 | 1107 | 1098 | 796 | 423 | 172 | 4899 | Summary |
| 35 | 11 | 20 | 21 | 18 | 9 | 2 | NULL | 81 | Detail |
| 35 | 10 | 25 | 30 | 23 | 12 | 1 | NULL | 101 | Detail |
| 35 | 21 | 45 | 51 | 41 | 21 | 3 | NULL | 182 | Summary |
| 38 | 25 | 35 | 35 | 35 | 20 | NULL | NULL | 150 | Detail |
| 38 | 25 | 35 | 35 | 35 | 20 | NULL | NULL | 150 | Detail |
| 38 | 50 | 70 | 70 | 70 | 40 | NULL | NULL | 300 | Summary |
| 39 | 65 | 86 | 86 | 42 | 21 | NULL | NULL | 300 | Detail |
| 39 | 42 | 58 | 58 | 28 | 14 | NULL | NULL | 200 | Detail |
| 39 | 107 | 144 | 144 | 70 | 35 | NULL | NULL | 500 | Summary |
+---------------+------+------+------+------+------+------+------+-------+---------+
This way, you know what is and what isn't a detail or summary row, and the order_main_id that it's for. You could always (and probably should) hide this column in your presentation layer.
For things like these I think you should use a reporting library(such as Crystal Reports), it'll save you a lot of trouble, check JasperReports and similar projects on osalt