SQL - Delete random rows where sum is equal to given number - sql

I want to get some random rows from the given table where the sum is 250(this can be changed). I don`t need to 100% accurate but can be approximate.
Like for 250 (1,5,7)
Note:- My table has huge data.
id | amount|
1 | 96 |
2 | 0.63 |
3 | 351.03 |
4 | 736|
5 | 53 |
6 | 39 |
7 | 105 |
8 | 91 |

For any specific numbers, you can return the closest sum using logic with joins. For instance for 3 numbers -- as in your example:
select t1.*, t2.*, t3.*
from t t1 join
t t2
on t1.id < t2.id join
t t3
on t2.id < t3.id
order by abs(250 - (t1.amount + t2.amount + t3.amount))
fetch first 1 row only;
Note that fetch first is standard SQL. Some databases spell it differently, for instance as limit or select top.

Related

How to create a calculated column in access that is based in a conditional sum of another table

It is possible in MS ACCESS 2016 to create a column in a table that is a conditional SUM of another table?
Example
Table 1 - Columns
ID, NAME, TOTAL
Table 2 - Columns
ID, NAME, IDREF, CUSTO
Data:
Table 1
ID | Name | Total
---+-------+----------------------------------------------------------------
35 | Test | "SUM(CUSTO) of ALL ELEMENTS OF TABLE 2 WHERE table2.IDREF = table1.ID"
Table 2
ID | Name | IDREF | CUSTO
---+-------+-------+--------
1 | Test | 35 | 50
2 | Test | 35 | 30
3 | abcd | 12 | 30
4 | Test | 35 | 10
The result should be:
table 1
ID | Name | Total
---+------+------
35 | Test | 90 (50 + 30 + 10 from table 2 where idref = 35)
You can use a subquery:
select t1.*,
(select sum(t2.CUSTO)
from table2 as t2
where t2.idref = t1.id
) as total
from table1 as t1;
More efficiently, consider an aggregate subquery in JOIN to run only once and not SELECT subquery that runs for every row.
SELECT t1.*, agg.Total
FROM table1 as t1
INNER JOIN
( SELECT t2.idref, SUM(t2.CUSTO) AS Total
FROM table2 as t2
GROUP BY t2.idref
) AS agg
ON agg.idref = t1.id
Alternatively, replace subquery with exact saved query for even more efficiency per Allen Browne's optimizing query tips in MS Access:
A subquery will be considerably faster than a domain aggregate function. In most cases, a stacked query will be faster yet (i.e. another saved query that you include as a "table" in this query.)
SELECT t1.*, q.Total
FROM table1 as t1
INNER JOIN mySavedAggQuery q
ON q.idref = t1.id

SQL that returns all the permutations of a summed column

Shot in the dark here. I'd personally struggle to come up with a simple SQL statement to do the following (if it can even be done), so I thought I'd throw this out here:
Let's say we have the following data:
ID VALUE
-- -----
1 60
2 60
3 60
4 60
And I wanted to find all the permutations of records that SUM to 120. Meaning, the results would be 6 rows:
1 AND 2
1 AND 3
1 AND 4
--2 AND 1 (already used)
2 AND 3
2 AND 4
--3 AND 1 (already used)
--3 AND 2 (already used)
3 AND 4
They actually want a "random sampling" of that result-set, but I need to know if I can even get that result-set. Of course, the real data wouldn't be that easy (everything 60), and the question was posed as "10 records that add up to 5 minutes" (the field is a duration field), which leads to other questions on how to handle that, but let me see if I can start with just getting permutations before actually getting more sophisticated.
Thanks.
These are combinations, not permutations. If you want all 2-way combinations, then use a self-join:
select t1.*, t2.*
from t t1 join
t t2
on t1.id < t2.id and
t1.value + t2.value = 60;
For an about 10% random sample, you can use:
select t1.*, t2.*
from t t1 join
t t2
on t1.id < t2.id and
t1.value + t2.value = 60
where rand() < 0.1;
select l.id, r.id, l.value+r.value as sum
from t l
inner join t r
on l.id < r.id
where l.value+r.value = 120
order by l.id, r.id
rextester demo: http://rextester.com/FWCLT49699
returns:
+----+----+-----+
| id | id | sum |
+----+----+-----+
| 1 | 2 | 120 |
| 1 | 3 | 120 |
| 1 | 4 | 120 |
| 2 | 3 | 120 |
| 2 | 4 | 120 |
| 3 | 4 | 120 |
+----+----+-----+
Table Tvalues
ID VALUE
-- -----
1 60
2 60
3 60
4 60
Select A.ID, B.ID from TValues A
join TValues B on B.ID != A.ID
where
(A.Value+B.Value) = 120
and
A.ID < B.ID -- eliminates dups, if (1,3) is printed, (3,1 will not be printed)

Query that countes pairs with same values depending on third column

I have three columns: Team_Code, ID, times_together.
I'm trying to count how many times ID's have the same "Team_Code" and add times_together to it.
In other words- I'm trying to write all the pairs of one column, check how many times they have the same value in other raw, and add third raw to it.
The simple way to ask this question is picture so:
Values can appear twice (for example
1110 with 8888
and then
8888 with 1110).
You could self join the table on team_code and sum the times_together:
SELECT t1.id, t2.id, SUM(t1.times_together)
FROM mytable t1
JOIN mytable t2 ON t1.team_code = t2.team_code AND t1.id != t2.id
If you want to make sure each pair only appears once, you could add a condition to always take the lower id on the left:
SELECT t1.id, t2.id, SUM(t1.times_together)
FROM mytable t1
JOIN mytable t2 ON t1.team_code = t2.team_code AND t1.id < t2.id
I would suggest this self-joining SQL which takes all possible ID pairs (but only where the first is smaller than the second), and uses a CASE to sum the times_together when the persons played in the same team:
select t1.id,
t2.id,
sum(case when t1.Team_Code = t2.Team_Code
then t1.times_together
else 0
end) times_together
from t as t1
inner join t as t2
on t1.id < t2.id
group by t1.id, t2.id
order by 1, 2
Output in the example case is:
| id | id | times_together |
|------|------|----------------|
| 1028 | 1110 | 0 |
| 1028 | 2220 | 0 |
| 1028 | 8888 | 0 |
| 1110 | 2220 | 1 |
| 1110 | 8888 | 1 |
| 2220 | 8888 | 6 |

To Compute difference of average of one quantity in one table from the quantity of the other table

i have two tables
Table1 & Table2
Prod | Reg | O.D | Qty Prod | Reg | F.d | qty
p1 | wwq | 4/1 | 10 p1 | wwq | 7/1 | 45
p1 | wwq | 5/1 | 20 p2 | ewq | 8/1 | 32
p1 | wwq | 6/1 | 30
p2 | ewq | 3/1 | 22
i want to take the difference of Qty of next from the AVERAGE QTY OF LAST TWO RECORDS (ORDERED BY O.D) and display the difference.
for eg. in table1 for prod p1 average of last two quantities ordered by O.D is (30 +20)/2 = 25 . and qty for same p1 in next is 45.
So, i want the difference as the answer . which is 45-25=20.
im new to sql and i wrote the following
SELECT (select avg(qty) from table1 where order by OD limit 2 ) - table2.qty
FROM table1 INNER JOIN table2
ON table1.prod=table2.prod and table1.reg=table2.reg
ORDER BY table1.OD;
prod and reg are super keys.
any help will be appreciated.
p.s- Sorry for the (no)formatting.
I am going to guess that you want one row per row in table 2, with the average in the first table being based on the date comparisons between the two tables. In that case, use a correlated subquery:
select t2.*,
(t2.qty -
(select avg(t1.qty)
from (select t1.*
from table1 t1
where t1.prod = t2.prod and
t1.reg = t2.reg and
t1.od <= f2.fd
order by t1.od desc
limit 2
) t1
)
) as diff
from table2 t2;

How to get a single result with columns from multiple records in a single table?

Platform: Oracle 10g
I have a table (let's call it t1) like this:
ID | FK_ID | SOME_VALUE | SOME_DATE
----+-------+------------+-----------
1 | 101 | 10 | 1-JAN-2013
2 | 101 | 20 | 1-JAN-2014
3 | 101 | 30 | 1-JAN-2015
4 | 102 | 150 | 1-JAN-2013
5 | 102 | 250 | 1-JAN-2014
6 | 102 | 350 | 1-JAN-2015
For each FK_ID I wish to show a single result showing the two most recent SOME_VALUEs. That is:
FK_ID | CURRENT | PREVIOUS
------+---------+---------
101 | 30 | 20
102 | 350 | 250
There is another table (lets call it t2) for the FK_ID, and it is here that there is a reference
saying which is the 'CURRENT' record. So a table like:
ID | FK_CURRENT | OTHER_FIELDS
----+------------+-------------
101 | 3 | ...
102 | 6 | ...
I was attempting this with a flawed sub query join along the lines of:
SELECT id, curr.some_value as current, prev.some_value as previous FROM t2
JOIN t1 curr ON t2.fk_current = t1.id
JOIN t1 prev ON t1.id = (
SELECT * FROM (
SELECT id FROM (
SELECT id, ROW_NUMBER() OVER (ORDER BY SOME_DATE DESC) as rno FROM t1
WHERE t1.fk_id = t2.id
) WHERE rno = 2
)
)
However the t1.fk_id = t2.id is flawed (i.e. wont run), as (I now know) you can't pass a parent
field value into a sub query more than one level deep.
Then I started wondering if Common Table Expressions (CTE) are the tool for this, but then I've no
experience using these (so would like to know I'm not going down the wrong track attempting to use them - if that is the tool).
So I guess the key complexity that is tripping me up is:
Determining the previous value by ordering, but while limiting it to the first record (and not the whole table). (Hence the somewhat convoluted sub query attempt.)
Otherwise, I can just write some code to first execute a query to get the 'current' value, and then
execute a second query to get the 'previous' - but I'd love to know how to solve this with a single
SQL query as it seems this would be a common enough thing to do (sure is with the DB I need to work
with).
Thanks!
Try an approach with LAG function:
SELECT FK_ID ,
SOME_VALUE as "CURRENT",
PREV_VALUE as Previous
FROM (
SELECT t1.*,
lag( some_value ) over (partition by fk_id order by some_date ) prev_value
FROM t1
) x
JOIN t2 on t2.id = x.fk_id
and t2.fk_current = x.id
Demo: http://sqlfiddle.com/#!4/d3e640/15
Try out this:
select t1.FK_ID ,t1.SOME_VALUE as CURRENT,
(select SOME_VALUE from t1 where p1.id2=t1.id and t1.fk_id=p1.fk_id) as PREVIOUS
from t1 inner join
(
select t1.fk_id, max(t1.id) as id1,max(t1.id)-1 as id2 from t1 group by t1.FK_ID
) as p1 on t1.id=p1.id1