I have two columns: amountFrom , amountTo in table shipping
Lets say I have these row data:
amountFrom | amountTo
-----------------------
0 15
16 30
31 50
Now I would like to add these three:
amountFrom | amountTo
-----------------------
15 22 (should fail, already exist (crosses range))
18 25 (should fail, already exist)
55 76 (should pass)
How can I make a correct sql query, that will run for each row i would like to insert, that will check if the "range" is available?
Example of what i tried
SELECT id FROM shipping WHERE amountFrom >= 15 AND amountTo <= 22
Above query returns no rows, which it should (if it was a correct query) since we dont want to make a new row with 15 and 22, as it will cross existing weight ranges
You can try this (here with values 15 and 22) :
INSERT INTO t (amountFrom, amountTo)
SELECT 15, 22
WHERE NOT EXISTS (SELECT 1 FROM t WHERE 22 >= amountFrom AND 15 <= amountTo);
You can check the affected-rows value to see wether or not the row was actually inserted.
You don't have to do three separate inserts. You can do them all at once (at least with the data in your query).
The select statement to see which do not overlap is:
select t2.*
from table2 t2
where not exists (select 1
from table1 t1
where t1.amountFrom <= t2.amountTo and
t1.amountTo >= t2.amountFrom
);
Two ranges overlaps if one starts before the other ends, and the first ends after the other starts.
You put this into an insert as
insert into t1(amountFrom, amountTo)
select t2.amountFrom, t2.amountTo
from table2 t2
where not exists (select 1
from table1 t1
where t1.amountFrom <= t2.amountTo and
t1.amountTo >= t2.amountFrom
);
EDIT:
If you want to do this one row at a time and prevent overlap in new rows as well:
insert into t1(amountFrom, amountTo)
select t2.amountFrom, t2.amountTo
from (select XX as amountfrom, YY as amountTo
) t2
where not exists (select 1
from table1 t1
where t1.amountFrom <= t2.amountTo and
t1.amountTo >= t2.amountFrom
);
This will do the insert one step at a time with the overlap logic.
Related
Hi Guys I have a question. I am still learning and am trying to get some date out. Beneath is the table. It has hundreds of lines, but for example:
FormNR
Datum
XX1
XX2
XX3
0001
2022-09-08
4
23
7
0002
2022-09-10
8
5
0
The table name is 'forms'. Now what I need to do is to count XX1+XX2+XX3 (for a year rapport). Then I have a 'date from and to' selection box on my page. So the question would be:
What instanties have been used between a certain date in total but so that you can see a a total per Instantie (each number is a different instantie).
So for example...Between the 1st of January and the 1st of June a list of all XX numbers ( there are 36 ) with there total behind it
What I have is the following. Is works great and shows all XX's in a nice table but for the entire table, not per date. As soon as i want to add the 'between $date_from AND $date_to' it fails.
<?php
$sql_rg_total="SELECT forms.Datum, x.f1,Count(x.f1)
FROM
(SELECT XX1 As F1 FROM forms
UNION ALL
SELECT XX2 As F1 FROM forms
UNION ALL
SELECT XX3 As F1 FROM forms) x
WHERE x.f1 = '$subcat_id'
GROUP BY x.f1";
$resultvv=mysqli_query($conn, $sql_rg_total);
if (mysqli_num_rows($resultvv) > 0) {
while ($rowvv = mysqli_fetch_assoc($resultvv)) {
$subnr = $rowvv['Count(x.f1)'];
echo $subnr;
}
}
?>
By the way $subcat_id is from another table which connects the number to a name.
I have tried to write it as clear as I could. I know it's a bit thought haha. Thanks anyway for any input. Really stuck.
This query should do it:
SELECT SUM(x.c) AS c
FROM (
SELECT ((XX1 = '$subcat_id') + (XX2 = '$subcat_id') + (XX3 = '$subcat_id')) AS c
FROM forms
WHERE Datum BETWEEN '$date_from' AND '$date_to'
) x
The value of a boolean condition is 1 when it's true, 0 when it's false. So XX1 = '$subcat_id' + XX2 = '$subcat_id' + XX3 = '$subcat_id' adds up the number of columns that match in a row, then SUM(c) totals them in the entire table.
You don't need GROUP BY, since it's the same column that you're filtering in the WHERE condition (and now in the SELECT expression). And this moves the date condition into the subquery.
i have 52k rows of records in my user table. In that table user_hash column having approximately 2000 duplicate values. i want to update user_hash columns 2nd duplicate value. The following table user_id (3, 10), (5, 14) having same value and i want to update user_id 10 and 14 values. how can i update it with MySQL Qry?
--------------------------------
user_id user_hash user_status
--------------------------------
1 ae57250b 1
2 310cb4e0 1
3 28b365c7 1
4 0073265b 1
5 8bec42a9 1
6 00a5c443 1
7 e1c27b19 1
8 993dc301 1
9 8fc8a6bf 1
10 28b365c7 1
11 194714c0 1
12 4611d83a 1
13 277a426b 1
14 8bec42a9 1
15 740c1412 1
... ... ...
... ... ...
... ... ...
The following qry which i have used to check duplicate entry
SELECT user_hash, COUNT(user_hash)
FROM user_data
GROUP BY user_hash
HAVING COUNT(user_hash) > 1;
The first thing that comes to mind is that you may want to define a constraint such that in the future you can't have non-unique values where you don't want them.
The second thing is to ensure that these hashes can't legitimately collide/overlap.
Those thoughts aside (as they may be irrelevant to your use case):
update user_data set user_data.user_hash = STORED_PROC_FOR_HASH()
from (
select *, row_number() over(partition by user_hash order by (select null)) row_num
from user_data
) user_data
where row_num > 1
Source for the above query: https://stackoverflow.com/a/25090251/3080207
As hinted at by Nick, you'll need to be able to generate a unique hash, which is pretty much the 2nd component to this problem.
Hopefully that is helpful.
Lets consider the following table-
ID Score
1 95
2 100
3 88
4 100
5 73
I am a total SQL noob but how do I return the Scores featuring both IDs 2 and 4?
So it should return 100 since its featured in both ID 2 and 4
This is an example of a "sets-within-sets" query. I recommend aggregation with the having clause, because it is the most flexible approach.
select score
from t
group by score
having sum(id = 2) > 0 and -- has id = 2
sum(id = 4) > 0 -- has id = 4
What this is doing is aggregating by score. Then the first part of the having clause (sum(id = 2)) is counting up how many "2"s there are per score. The second is counting up how many "4"s. Only scores that have at a "2" and "4" are returned.
SELECT score
FROM t
WHERE id in (2, 4)
HAVING COUNT(*) = 2 /* replace this with the number of IDs */
This selects the rows with ID 2 and 4. The HAVING clause then ensures that we found both rows; if either is missing, the count will be less than 2.
This assumes that id is a unique column.
select Score
from tbl a
where a.ID = 2 -- based off Score with ID = 2
--include Score only if it exists with ID 6 also
and exists (
select 1
from tbl b
where b.Score = a.Score and b.ID = 6
)
-- optional? ignore Score that exists with other ids as well
and not exists (
select 1
from tbl c
where c.Score = a.Score and c.ID not in (2, 6)
)
I have a database, db and in it a table, Table.
It looks somewhat like:
id | val
--------
1 | 45
2 | 35
3 | 23
4 | 49
5 | 67
6 | 12
7 | 0
8 | 87
9 | 46
(This is just an example data set. Actual data set is huge. And I need to work in least time possible.)
I need to find the median of the column val. Actually I need a php function to be used multiple times.
A similar question does exist: Simple way to calculate median with MySQL
I tried a few answers in this question, none of them worked for me. The accepted answer doesn't work since it used to work with an older version of SQL only.
PS: It should also work in the case of many duplicates.
just for fun i thought i try and do it all in MySQL, here's the sqlFiddle
SELECT
CASE
WHEN MOD((select count(*) as count from t),2)=1 THEN
(select val from
(select #row:=#row+1 as row,val
from t,(select #row:=0)r
order by val)t1
where t1.row = CEIL((select count(*) as count from t)/2)
)
ELSE
((select val from
(select #row:=#row+1 as row,val
from t,(select #row:=0)r
order by val)t1
where t1.row = (select count(*) as count from t)/2)+
(select val from
(select #row:=#row+1 as row,val
from t,(select #row:=0)r
order by val)t1
where t1.row = ((select count(*) as count from t)/2)+1))/2
END AS median
Just replace occurences of t with your table name, don't change t1.
Also if the table has no rows, it'll return NULL as median.
This query can be further reduced to the below (sqlFiddle)
SELECT #rowCount:=(select count(*) as count from t) AS rowcount,
(select AVG(val) from
(select #row:=#row+1 as row,val
from t,(select #row:=0)r
order by val)t1
where t1.row IN (FLOOR((#rowCount+1)/2),
CEIL((#rowCount+1)/2)
)
) as Median
It'll return 2 columns, a rowcount column and a median column. I put the rowcount column there because i didn't want to count from t multiple times like previous query.
I am recording a real time change of a given signal into my database table.
Then I draw line graph to visualize the change of the signal level.
I want to get (10n+1)th rows in the table to make a rough graph. 10 is also arbitrary. User may change it to another value.
Does someone know how to make this just using a MySQL Query
If no, I will go with PHP after selecting all the data.
Here my table structure is:
|id |signal1 |signal2 | signal 3 |
+----------+----------+----------+------------+
|1 |0.41452 | 1.32135 | 0.31231 |
...
If you have an auto_incrememt id column, you can select rows that are divisible by n
SELECT * FROM tableName1 WHERE MOD(id,10)=0;
// id divided by 10 with a remainder equal to 0 (exact)
or without sequential column id's
SELECT * FROM (
SELECT
#row := #row +1 AS rowNum, colName1
FROM (
SELECT #row :=0) r, tableName1
) ranked
WHERE rowNum % 10 = 1
If your table has auto increment id (intID), then you should try this code.There are only 26 records in my table.
select * from tablename where intId
in (select case (intId%10=0) when 1 then intId else 0 end as x from tablename )
Output :-
10 sdf KK201300010 123456 Regular
20 sdf KK201300020 123456 Regular
It will displaying each record in every 10 record.
Hope it will help you.