Sqlite: Selecting records spread over total records - sql

I have a sql / sqlite question. I need to write a query that select some values from a sqlite database table. I always want the maximal returned records to be 20. If the total selected records are more than 20 I need to select 20 records that are spread evenly (no random) over the total records. It is also important that I always select the first and last value from the table when sorted on the date. These records should be inserted first and last in the result.
I know how to accomplish this in code but it would be perfect to have a sqlite query that can do the same.
The query Im using now is really simple and looks like this:
"SELECT value,date,valueid FROM tblvalue WHERE tblvalue.deleted=0 ORDER BY DATE(date)"
If I for example have these records in the talbe and to make an easier example the maximum result I want is 5.
id value date
1 10 2010-04-10
2 8 2010-04-11
3 8 2010-04-13
4 9 2010-04-15
5 10 2010-04-16
6 9 2010-04-17
7 8 2010-04-18
8 11 2010-04-19
9 9 2010-04-20
10 10 2010-04-24
The result I would like is spread evenly like this:
id value date
1 10 2010-04-10
3 8 2010-04-13
5 10 2010-04-16
7 8 2010-04-18
10 10 2010-04-24
Hope that explain what I want, thanks!

Something like this should work for you:
SELECT *
FROM (
SELECT v.value, v.date, v.valueid
FROM tblvalue v
LEFT OUTER JOIN (
SELECT min(DATE(date)) as MinDate, max(DATE(date)) as MaxDate
FROM tblvalue
WHERE tblvalue.deleted = 0
) vm on DATE(v.date) = vm.MinDate or DATE(v.date) = vm.MaxDate
WHERE tblvalue.deleted = 0
ORDER BY vm.MinDate desc, Random()
LIMIT 20
) a
ORDER BY DATE(date)

I think you want this:
SELECT value,date,valueid FROM tblvalue WHERE tblvalue.deleted=0
ORDER BY DATE(date), Random()
LIMIT 20

In other words you want select rows with date column, so that date is from the sorted list of dates, from where we take every odd element? And add the last recorded element (with the latest date)? And everything limited to max 20 rows?
If that's the case, then I think this one should do:
SELECT id,value,date FROM source_table WHERE date IN (SELECT date FROM source_table WHERE (rowid-1) % 2 = 0 OR date = (SELECT max(date) FROM source_table) ORDER BY date) LIMIT 20

Related

Return all the second highest valued rows SQL

Let's say I have a table called bookings, containing 3 columns: hotelid, timestampOfBookingand numberOfGuests.
How do I return all the dates on which the second highest beds were booked (the amount of beds booked is the same as the number of guests).
In other words, I'm looking for the dates on which the second maximum number of numberOfGuestsoccur. This means that in the event of a tie (where there is more than 1 date on which the described condition applies), it should return all those dates. In the event that all the dates have exactly the same numberOfGuests the query should return nothing.
If possible, I would only like to have one column in the query result that contains those specific dates.
Example:
hotelid timestampOfBooking numberOfGuests
11 22/11/2021 2
34 23/11/2021 2
30 23/11/2021 5
19 24/11/2021 7
8 25/11/2021 12
34 25/11/2021 5
In this case two dates should be in the result: 23/11/2021 and 24/11/2021 as they both had 7 numberOfGuests. The max numberOfGuests here is 17 (occurs on 25/11/2021) and 7 is the second highest, explaining why 23/11/2021 (2 + 5) and 24/11/2021 (7) are returned. The final result should look like this:
dates
23/11/2021
24/11/2021
Method 1:
You can use DENSE_RANK() with SUM(numberOfGuests) IN DESC:
SELECT timestampOfBooking, total_beds FROM
(
select timestampOfBooking,
sum(numberOfGuests) as total_beds,
dense_rank() over (order by sum(numberOfGuests) DESC) as rnk
from bookings
group by timestampOfBooking
) as sq
where rnk = 2
Method 2:
Using OFFSET and LIMIT:
SELECT timestampOfBooking,
SUM(numberOfGuests) AS total_beds
FROM bookings
GROUP BY timestampOfBooking
HAVING sum(numberOfGuests)=
(
SELECT distinct SUM(numberOfGuests) AS total_beds
FROM bookings
GROUP BY timestampOfBooking
ORDER BY total_beds DESC
OFFSET 1 LIMIT 1
);
Both the methods will give you same output.
Working fiddle

Querying Data Backward in ORACLE SQL

I have a simple question regarding oracle sql. So i have this table
WEEKNUM DATA
1 10
2 4
3 6
4 7
So i want to make a view that shows like this,
WEEKNUM DATA ACCUM_DATE
1 10 10
2 4 14
3 6 20
4 7 27
I spend hours on this simple one but couldnt get any luck
thanks a lot
SELECT weeknum,
data,
sum(data) over (order by weeknum) accum_data
FROM your_table_name
should work. I'm using the sum analytic function here and assuming that you want to start with the smallest weeknum value and keep increasing the running total as the weeknum values increase. I'm also assuming that you never want to reset the accumulated sum. If you're trying to do something like generating an accumulated sum that restarts each year, you'd want to add a partition by to the analytic function.
You could use a Cross JOin in this case
Query:
select
A.WEEKNUM
, A.DATA
, SUM(B.DATA) DA
from table1 A
cross join table1 B
WHERE A.WEEKNUM>=B.WeekNUM
GROUP BY A.WEEKNUM
, A.DATA
order by A.WEEKNUM
Result:
WEEKNUM DATA DA
1 10 10
2 4 14
3 6 20
4 7 27
Thanks guys but i just found out this method works perfectly,
OVER (ORDER BY WEEKNUM ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS CUMULATIVE_WEIGHT
Or use a sub-select to calculate:
select WEEKNUM, DATA, (select sum(DATA) from tablename t2
where t2.weeknum <= t1.weeknum) as ACCUM_DATE
from tablename t1

counting subquery in SQL

I have the following query to count how many times each process_track_id occurs in a table:
SELECT
a.process_track_id,
COUNT(1) AS 'num'
FROM
transreport.process_name a
GROUP BY
a.process_track_id
This returns the following results:
process_track_id | num
1 14
2 44
3 16
5 8
6 18
7 17
8 14
This is great. Now is the part where I am stuck. I would like to get the following table:
num count
8 1
14 2
16 1
17 1
18 1
44 1
Where num are the distinct counts from the first table, and count is how many times that frequency occurs.
Here is what I have tried (it's a subquery, but I'm not sold on the method) and I haven't been able to get it to work just yet. I'm new to SQL and I think I'm missing out on some some key aspects of the syntax.
SELECT
X.id_count,
count(1) as 'num_count'
FROM
(SELECT
a.process_track_id,
COUNT(1) AS 'id_count'
FROM
transreport.process_name a
GROUP BY
a.process_track_id
--COUNT(1) AS 'id_count'
) X;
Any ideas?
It's probably good to keep in mind that this may have to be run on a database with at least 1 million records, and I don't have the ability to create a new table in the process.
Thanks!
Here's the subquery method you were driving at:
SELECT id_count, COUNT(*) AS 'num_count'
FROM (SELECT a.process_track_id
,COUNT(*) AS 'id_count'
FROM transreport.process_name a
GROUP BY a.process_track_id
)sub
GROUP BY id_count
Not sure there's a better method as the aggregation needs to run once anyway.
Try this
SELECT x.num, COUNT(*) AS COUNT
FROM (
SELECT
a.process_track_id, -- <--- You may removed this column
COUNT(*) AS 'num'
FROM
transreport.process_name a
GROUP BY
a.process_track_id
) X
GROUP BY X.num

SQL Query to find which group does not have a given value

I am using T-SQL.
Say if I have the following
Value Nbr
----- ---
one 6
one 7
one 8
two 6
two 7
three 5
three 3
three 2
In the above table, I need to find which group does not have 6 in it.
In this case, it is three as it does not have 6 in it.
What would be the best approach to do this?
I tried:
select Value from tbl1
where nbr <> 6
group by Value
but did not get the intended result.
select distinct value
from tbl1
where value not in
(
select distinct value
from tbl1
where nbr = 6
)

SQLite: Get Total/Sum of Column

I am using SQLite and am trying to return the total of one column buy_price in the column TOTAL while at the same time returning all of the data. I do not want/need to group the data as I need to have the data in each returned row.
id date pool_name pool_id buy_price TOTAL
1 09/01/12 azp 5 20
2 09/02/12 mmp 6 10
3 09/03/12 pbp 4 5
4 09/04/12 azp 7 20
5 09/05/12 nyp 8 5 60
When I include something like SUM(buy_price) as TOTAL it only returns one row. I need all rows returned along with the total of all buy_price entries.
It sounds like this is what you are looking for:
select id,
dt,
pool_name,
pool_id,
buy_price,
(select sum(buy_price) from yourtable) total
from yourtable
see SQL Fiddle with Demo
Select * from yourtable
union
select 'Total',
' ',
' ',
' ',
sum(buy_price)
from yourtable
you can add a row on the bottom like this instead of adding a new column...