Select all items with sum of fields in specified range - sql

I have simple table:
file_size file_id file_time
1 1 19
2 2 20
3 3 21
4 4 22
5 5 23
I want to find such item that all items with less file_time has the sum of file_size in predefined range.
I written next query:
SELECT * FROM test_table AS D0 WHERE
(SELECT TOTAL(file_size) FROM test_table AS D1 WHERE
D1.file_time <= D0.file_time ORDER BY file_id)
BETWEEN 1 AND 9
This query get correct results:
1 1 19
2 2 20
3 3 21
But this query does not work if needed items has the same file_time field:
file_size file_id file_time
1 1 20
2 2 20
3 3 20
4 4 20
5 5 20
The desired result for this data is:
1 1 20
2 2 20
3 3 20
The file_id field is unique.
What is wrong in my SQL-query?
The code to create test table:
CREATE TABLE test_table (file_size INT, file_id INT, file_time INT)
INSERT INTO test_table VALUES(1,1,20)
INSERT INTO test_table VALUES(2,2,20)
INSERT INTO test_table VALUES(3,3,20)
INSERT INTO test_table VALUES(4,4,20)
INSERT INTO test_table VALUES(5,5,20)

You shouldn't consider file_time as a single column in your query, since you want to consider the column file_id either. You should use the pairs of file_time and file_id and you should compare them lexicographically as follows:
SELECT *
FROM test_table AS D0
WHERE (
SELECT TOTAL( file_size )
FROM test_table AS D1
WHERE D1.file_time < D0.file_time
OR (
D1.file_time = D0.file_time
AND D1.file_id <= D0.file_id
)
ORDER BY file_time, file_id DESC
)
BETWEEN 1
AND 9

Not sure if I understood but I think
-- sum of file sizes between 1 and 7 with the lowest time
SELECT SUM(test.file_size) AS sum_file_size, test.file_time
FROM test
WHERE (test.file_time = (SELECT TOP 1 test.file_time
FROM test
ORDER BY file_time))
AND (test.file_size BETWEEN 1 AND 9)
GROUP BY test.file_time;
-- sum of file sizes per time `group`
SELECT SUM(test.file_size) AS sum_file_size, test.file_time,
FROM test
WHERE (test.file_size BETWEEN 1 AND 7)
GROUP BY test.file_time
ORDER BY test.file_time;

Related

offset does not work with Count(*) as order by

I have a query with Count(*) as order by with offset fetch next. When I am using different values as offset it is always providing the same resultset.
I tried with some column as order by where the resultset varies and it worked perfectly fine. Can someone help with this.
select
Id,
count(*) as "Count"
from
some_table
group by
"Id"
Order By
"Count" ASC OFFSET 0 ROWS FETCH NEXT 5 ROWS ONLY;
Screenshot 1
Screenshot 2
This is your query:
select Id, count(*) as "Count"
from some_table
group by "Id"
order by "Count" asc
OFFSET 0 ROWS FETCH NEXT 5 ROWS ONLY;
The problem is that you have duplicate values for count(*). Because SQL tables represent unordered sets, it has no default ordering. That poses a problem when sort keys have the same value.
The simple solution is to include id in the order by:
order by "Count" asc, id
This makes the sort stable, so it is well-defined.
here is the My example
Create a Table
create table t (id int, name varchar(100))
insert data's
insert into t values(1,'saravnan')
insert into t values(1,'kumar')
insert into t values(1,'Ravi')
insert into t values(1,'mohan')
insert into t values(2,'Raju')
insert into t values(2,'Vikram')
insert into t values(2,'AA')
insert into t values(2,'BB')
insert into t values(2,'CC')
insert into t values(2,'DD')
insert into t values(2,'EE')
insert into t values(3,'Raju')
insert into t values(3,'Vikram')
insert into t values(3,'AA')
insert into t values(4,'BB')
insert into t values(4,'CC')
insert into t values(4,'DD')
insert into t values(4,'EE')
select all data
select *from t
id name
1 1 saravnan
2 1 kumar
3 1 Ravi
4 1 mohan
5 2 Raju
6 2 Vikram
7 2 AA
8 2 BB
9 2 CC
10 2 DD
11 2 EE
12 3 Raju
13 3 Vikram
14 3 AA
15 4 BB
16 4 CC
17 4 DD
18 4 EE
offset is used for Number of rows skip from start of the table data. it should be number.
here my example:
select id,count(*) from t group by id order by id offset 1 rows fetch next 3 row only
It returns
id count
1 2 7
2 3 3
3 4 4
The fetch next used for number rows to return.
Solution for your example .
--offset 0 returns[enter image description here][1]
select Id,count(1) as "Count" from t group by ID Order By "Count" ASC OFFSET 0 ROWS FETCH NEXT 5 ROWS ONLY
Id Count
1 3 3
2 4 4
3 1 4
4 2 7
-- offset 1 returns
select Id,count(1) as "Count" from t group by ID Order By "Count" ASC OFFSET 1 ROWS FETCH NEXT 5 ROWS ONLY
Id Count
1 4 4
2 1 4
3 2 7

How to update table with concatenation

I have table like this
create table aaa (id int not null, data varchar(50), numb int);
with data like this
begin
for i in 1..30 loop
insert into aaa
values (i, dbms_random.string('L',1),dbms_random.value(0,10));
end loop;
end;
now im making this
select a.id, a.data, a.numb,
count(*) over (partition by a.numb order by a.data) count,
b.id, b.data,b.numb
from aaa a, aaa b
where a.numb=b.numb
and a.data!=b.data
order by a.data;
and i want to update every row where those numbers are the same but with different letters, and in result i want to have new data with more than one letter (for example in data column- "a c d e"), i just want to create concatenation within. How can i make that? the point is to make something like group by for number but for that grouped column i would like to put additional value.
that is how it looks like in begining
id | data |numb
1 q 1
2 z 8
3 i 7
4 a 2
5 q 4
6 h 1
7 b 9
8 u 9
9 s 4
That i would like to get at end
id | data |numb
1 q h 1
2 z 8
3 i 7
4 a 2
5 q s 4
7 b u 9
Try this
SELECT MIN(id),
LISTAGG(data,' ') WITHIN GROUP(
ORDER BY data
) data,
numb
FROM aaa GROUP BY numb
ORDER BY 1
Demo
This selects 10 random strings 1 to 4 letters long, letters in words may repeat:
select level, dbms_random.string('l', dbms_random.value(1, 4))
from dual connect by level <= 10
This selects 1 to 10 random strings 1 to 26 letters long, letters do not repeat and are sorted:
with aaa(id, data, numb) as (
select level, dbms_random.string('L', 1),
round(dbms_random.value(0, 10))
from dual connect by level <= 30)
select numb, listagg(data) within group (order by data) list
from (select distinct data, numb from aaa)
group by numb

Get offset of a row after performing sort operation in sql

I am using SQLite database.
Suppose I have rows with IDs 1 to 50. Then I perform select and order by operation.
Say, the result is IDs : 6,3,5,2,9,12,1,34,45,15.
Now, I want to know the offset of a particular row with given ID in the above result.e.g. offset of ID 1 is 6.
Can I do this in a single query?
put the query of ordered result into a subquery and use count(*) and check the id sequence:
Example:
SCHEMA:
CREATE TABLE tbl ("id" INTEGER,"val" INTEGER);
INSERT INTO tbl ("id","val")
VALUES
(12,6),(1,7),(34,8),(6,1),(9,5),
(45,9),(15,10),(3,2),(5,3),(2,4);
QUERY:
select id,(
select count(*)
from (
select id,val
from tbl order by val
) b
where a.val >= b.val)-1 as offset
from tbl a
order by offset
RESULT:
id offset
6 0
3 1
5 2
2 3
9 4
12 5
1 6
34 7
45 8
15 9
SQLFIDDLE DEMO

Insert rows based on number of distinct values in another table in SQL

I have a table with PO#,Days_to_travel, and Days_warehouse fields. I take the distinct Days_in_warehouse values in the table and insert them into a temp table. I want a script that will insert all of the values in the Days_in_warehouse field from the temp table into the Days_in_warehouse_batch row in table 1 by PO# duplicating the PO records until all of the POs have a record per distinct value.
Example:
Temp table: (Contains only one field with all distinct values in table 1)
Days_in_warehouse
20
30
40
Table 1 :
PO# Days_to_travel Days_in_warehouse Days_in_warehouse_batch
1 10 20
2 5 30
3 7 40
Updated Table 1:
PO# Days_to_travel Days_in_warehouse Days_in_warehouse_batch
1 10 20 20
1 10 20 30
1 10 20 40
2 5 30 20
2 5 30 30
2 5 30 40
3 7 40 20
3 7 40 30
3 7 40 40
Any ideas as to how can I update Table 1 to see desired results?
One more way without a TEMP table and DELETE.
UPDATE T SET [Days_in_warehouse_batch] = [Days_in_warehouse];
INSERT INTO T ([PO], [Days_to_travel],
[Days_in_warehouse], [Days_in_warehouse_batch])
SELECT T.PO,
T.Days_to_travel,
T.Days_in_warehouse,
DAYS_Table.Days_in_warehouse
FROM T
CROSS JOIN
(SELECT DISTINCT Days_in_warehouse FROM T) as DAYS_Table
WHERE T.Days_in_warehouse <> DAYS_Table.Days_in_warehouse;
SQLFiddle demo
I would suggest the following:
insert into table1(PO#, Days_to_travel, Days_in_warehouse, Days_in_warehouse_batch)
select PO#, Days_to_travel, Days_in_warehouse, Days_in_warehouse
from table1 cross join
(select 20 as Days_in_warehouse union all select 30 union all select 40) var
where Days_in_warehouse_batch is null;
delete from table1
where Days_in_warehouse_batch is null;
What you're looking for is the cartesian product between your two tables.
select t1.po, t1.daystotravel, t1.daysinwarehouse, temp.daysinwarehousebatch
from table1 t1, temp
The easiest way I can think of updating table1 with these values is to insert them, and then delete the originals.
insert into table1
select t1.po, t1.daystotravel, t1.daysinwarehouse, temp.daysinwarehousebatch
from table1 t1, temp
And then delete the originals:
delete from table1 where daysinwarehousebatch is null
SQL Fiddle Demo

SQL - Add value with previous row only

I have a table named myvals with the following fields:
ID number
-- -------
1 7
2 3
3 4
4 0
5 9
Starting on 2nd row, I would like to add the number with the previous row number. So, my end result would look like this
ID number
-- ------
1 7
2 10
3 7
4 4
5 9
You could use the LAG analytic function
SELECT Id, number + LAG(number,1,0) OVER (ORDER BY Id) FROM table
First thing's first. You can't add to null to ID 1 must have a value.
create table #temp
(
month_type datetime,
value int
)
insert into #temp
Select '2015/01/01',1
union
Select '2015/02/01',2
union
Select '2015/03/01',3
union
Select '2015/04/01',4
SELECT t.value,t1.value,(t.value+t1.value)/2 FROM #temp t1
left join #temp t on t.month_type=Dateadd(MONTH,-1,t1.month_type)