here is the table and values
ID c1 c2 c3 c4 c5
______________________
1 60 11 29 50 90
2 59 12 32 51 81
3 61 16 30 53 92
4 66 13 34 55 91
5 57 14 28 49 73
and this is the list of numbers [59,13,33,56,94] (I mean 59 for c1 , 13 for c2 and ..)
now how to select top 3 closest record base on list
I suspect that you may mean closest by something like Euclidean distance.
The idea is order by and limit:
select t.*
from t
order by pow(c1 - 59, 2) + pow(c2 - 13, 2) + pow(c3 - 33, 2) +
pow(c4 - 56, 2) + pow(c5 - 94, 2)
limit 3;
You could use:
SELECT *, ABS(c1-a1) + ABS(c2-a2) + ABS(c3-a3) + ABS(c4 - a4) + ABS(c5-a5) AS total
FROM tab
CROSS JOIN (SELECT 59 a1,13 a2,33 a3,56 a4,94 a5) l
ORDER BY total LIMIT 3
Related
I have the following columns:
2022-05-25T17:31:34+0000 92 7 1
2022-05-25T16:06:46+0000 50 5 9
2022-05-25T13:05:27+0000 91 10 106
2022-05-25T09:17:01+0000 48 4 4
2022-05-25T08:43:05+0000 60 4 2
2022-05-25T06:26:38+0000 24 3 6
2022-05-24T15:14:49+0000 55 12 6
2022-05-24T12:25:35+0000 43 8 2
2022-05-24T11:15:24+0000 66 7 2
2022-05-24T10:45:56+0000 37 15 2
2022-05-23T17:51:09+0000 59 7 1
2022-05-23T17:50:44+0000 47 6 3
2022-05-23T15:48:02+0000 126 7 13
2022-05-23T11:42:26+0000 64 9 9
2022-05-27T06:00:29+0000 3 0 1
2022-05-25T17:31:34+0000 96 7 1
2022-05-25T16:06:46+0000 55 5 9
2022-05-25T13:05:27+0000 99 11 116
2022-05-25T09:17:01+0000 52 4 15
2022-05-25T08:43:05+0000 61 4 2
2022-05-25T06:26:38+0000 26 3 6
2022-05-24T15:14:49+0000 57 13 7
2022-05-24T12:25:35+0000 43 8 2
2022-05-24T11:15:24+0000 66 7 2
2022-05-24T10:45:56+0000 38 15 2
2022-05-23T17:51:09+0000 59 7 1
2022-05-23T17:50:44+0000 47 6 3
2022-05-23T15:48:02+0000 127 7 13
If you look at the 16th row it has the same date as the first row but the number of PostLikes are different (92 and 96) PostComments and PostShares also change. I want to create a stored procedure where when I input the date it will return the difference. For example, if I select the third row with date 2022-05-25T13:05:27+0000 it should give the result:
DateT PostLikes PostComments PostShares
2022-05-25T13:05:27+0000 7 1 10
Now one method of doing this is:
select max(PostLikes) - min(PostLikes) as LikeDifference, max(PostComments) - min(PostComments) as CommentDifference, max(PostShares) - min(PostShares) as ShareDifference
from kpitb.userLikes
where DateT = "2022-05-25T17:31:34+0000";
But this method is only good if there are two values, the database is going to have several values with the same dates. (Note DateT is VARCHAR)
For e.g.
Row 1 2022-05-25T13:05:27+0000 24
Row 2 2022-05-25T13:05:27+0000 34
Row 3 2022-05-25T13:05:27+0000 67
How to find the difference.
Any help would be appreciated.
Using window functions you can find the max id and the previous values and the main query becomes trivial.
with cte as
(select t.*,
lag(postlikes) over(partition by datet order by id) prevlikes,
lag(postcomments) over(partition by datet order by id) prevcomments,
lag(postshares) over(partition by datet order by id) prevshares,
t1.maxid
from t
join (select max(id) maxid,datet from t group by datet) t1 on t1.datet = t.datet
order by datet,id
)
select datet,
case when prevlikes is null then postlikes else postlikes - prevlikes end likes,
case when prevcomments is null then postcomments else postcomments - prevcomments end comments,
case when prevshares is null then postshares else postshares - prevshares end shares
from cte
where id = maxid;
https://dev.mysql.com/doc/refman/8.0/en/window-functions.html
Sql Table
Sales Date order Id customer_id medium
07-07-2018 WP241530914666620 26 4
21-07-2018 WP241532133344497 26 4
29-07-2018 WP241532821589511 26 4
01-07-2018 1100070191 61 3
05-07-2018 1100071337 61 3
11-07-2018 1100073077 61 3
15-07-2018 1100074754 61 3
21-07-2018 1100075959 61 3
25-07-2018 1100077484 61 3
01-07-2018 100207654 64 3
07-07-2018 100210077 64 3
08-07-2018 WP241531004708220 64 4
Result:-
Sales Date order Id customer_id medium
07-07-2018 WP241530914666620 26 4
21-07-2018 WP241532133344497 26 4
29-07-2018 WP241532821589511 26 4
01-07-2018 1100070191 61 3
05-07-2018 1100071337 61 3
11-07-2018 1100073077 61 3
i need mysql query for above result .
last 3 orders for each customers in above table . i am trying some codes but unable to get results for the above
You could using correlated subqueries like:
select Sales_Date,order_Id,customer_id,medium
from
(select y1.Sales_Date,y1.order_Id,y1.customer_id,y1.medium,
(select count(*)
from 'yourtable' y2
where y2.customer_id=y1.customer_id
and (y2.Sales_Date < y1.Sales_Date or y2.Sales_Date = y1.Sales_Date)
) rn
from 'yourtable' y1
) finalresult
where rn<=3
Reference:
correlated subqueries
Example
I have a database with a Datetime column containing intervals of +/- 30 seconds and a Value column containing random numbers between 10 and 100. My table looks like this:
datetime value
----------------------------
2016-05-04 20:47:20 12
2016-05-04 20:47:40 44
2016-05-04 20:48:30 56
2016-05-04 20:48:40 25
2016-05-04 20:49:30 92
2016-05-04 20:49:40 61
2016-05-04 20:50:00 79
2016-05-04 20:51:20 76
2016-05-04 20:51:30 10
2016-05-04 20:51:40 47
2016-05-04 20:52:40 23
2016-05-04 20:54:00 40
2016-05-04 20:54:10 18
2016-05-04 20:54:50 12
2016-05-04 20:56:00 55
What I want the following output:
datetime max_val min_val
-----------------------------------------
2016-05-04 20:45:00 92 12
2016-05-04 20:50:00 79 10
2016-05-04 20:55:00 55 55
Before I can even continue getting the maximum value and the minimum value, I first have to GROUP the datetime column into 5 minute intervals. According to my research I came up with this:
SELECT
time,
value
FROM random_number_minute
GROUP BY
UNIX_TIMESTAMP(time) DIV 300
Which actually GROUPS the datetime column into 5 minute intervals like this:
datetime
-------------------
2016-05-04 20:47:20
2016-05-04 20:50:00
2016-05-04 20:56:00
This comes very close as it takes the next closest datetime to, in this case, 20:45:00, 20:50:00, etc. I would like to rounddown the datetime to the nearest 5 minutes regardless of the seconds, for instance if the minutes are:
minutes rounddown
--------------------
10 10
11 10
12 10
13 10
14 10
15 15
16 15
17 15
18 15
19 15
20 20
The time could be 14:59 and I would like to rounddown to 10:00. I also tried using this after hours of research:
SELECT
time,
time_rounded =
dateadd(mi,(datepart(mi,dateadd(mi,1,time))/5)*5,dateadd(hh,datediff(hh,0,dateadd(mi,1,time)),0))
But sadly this did not work. I get this error:
Incorrect parameter count in the call to native function 'datediff'
I tried this too:
SELECT
time, CASE
WHEN DATEDIFF(second, DATEADD(second, DATEDIFF(second, 0, time_out) / 300 * 300, 0), time) >= 240
THEN DATEADD(second, (DATEDIFF(second, 0, time) / 300 * 300) + 300, 0)
ELSE DATEADD(second, DATEDIFF(second, 0, time) / 300 * 300, 0)
END
Returning the same error.
How can I do this? And after the datetime is grouped, how can I get the max and min value of the data grouping?
Sorry if I'm repeating another answer. I'll delete if I am..
SELECT FROM_UNIXTIME(FLOOR(UNIX_TIMESTAMP(datetime)/300)*300) x
, MIN(value) min_value
, MAX(value) max_value
FROM my_table
GROUP
BY x;
Use various date partition functions inside a GROUP BY.
Code:
SELECT from_unixtime(300 * round(unix_timestamp(r.datetime)/300)) AS 5datetime,
MAX(r.value) AS max_value,
MIN(r.value) As min_value,
(SELECT r.value FROM random_number_minute ra WHERE ra.datetime = r.datetime order by ra.datetime desc LIMIT 1) as first_val
FROM random_number_minute r
GROUP BY UNIX_TIMESTAMP(r.datetime) DIV 300
Output:
5datetime max_value min_value first_val
May, 04 2016 20:45:00 92 12 12
May, 04 2016 20:50:00 79 10 79
May, 04 2016 20:55:00 55 55 55
SQL Fiddle: http://sqlfiddle.com/#!9/e16b1/17/0
SELECT
timestamp(concat(date(time), ' ', hour(time), ':', minute(time) div 5 * 5)) as floor_time,
min(value),
max(value)
FROM random_number_minute
GROUP BY date(time), hour(time), minute(time) div 5 * 5
http://sqlfiddle.com/#!9/91212f/5
I have an sql table that saves Locations,
ID Name X Y Z
-------------------------
1 Loc1 12 24 45
2 Loc2 12 24 60
3 Loc3 54 32 33
4 Loc4 54 32 64
5 Loc5 98 66 90
6 Loc6 98 66 77
7 Loc7 44 50 98
Some Location coordinates (x and y) are duplicated by mistake
I want to select and delete one of them.
ID Name X Y Z
-------------------------
1 Loc1 12 24 45
2 Loc3 54 32 33
3 Loc5 98 66 90
4 Loc7 44 50 98
Is this possible with sql query?
I think you can use the alter-table command and just drop the whole column.
ALTER TABLE table_name
DROP COLUMN column_name
with cte
as
(
select *,row_number() over (partition by x,y order by x) as rn
)
delete from cte where rn>1
As seen pointed out in comments,this deletes a random row (undeterministic),to make it deterministic order by name in your case
For MySQL you can use:
DELETE mytable
FROM mytable
JOIN (SELECT MIN(ID) AS ID, X, Y
FROM mytable
GROUP BY X, Y
) AS t ON mytable.X = t.X AND mytable.Y = t.Y AND mytable.ID > t.ID
Demo here
Its easy:
Add an INDEX over the 2 Columns with IGNORE:
ALTER IGNORE TABLE YOUR_TABLE
ADD KEY (X,Y);
Thats all
id date group n1 n2 n3 n4 n5
18853 1945-01-05 BA 87 34 1 59 50
18854 1945-01-13 BA 6 66 1 16 48 <= the last 16, 7 rows to the end
18855 1945-01-20 BA 38 14 24 78 36
18856 1945-01-27 BA 49 30 87 15 65 <= the last 49, 5 rows to the end
18857 1945-02-03 BA 30 64 36 5 32
18858 1945-02-10 BA 15 36 37 86 31 <= the last 36, 3 rows to the end
18859 1945-02-17 BA 86 78 69 7 60 <= the last 86, 2 rows to the end
18860 1945-02-24 BA 83 7 72 88 19 <= the last 7, 1 row to the end
18861 1945-03-03 BA 47 20 77 73 30 <= the last 47, 0 rows to the end
I have the above table (it's ordered by id, however I plan to order it by date). Is there a way to get the number of rows between a specified number and the last row in mySql?
Note that some numbers are repeated twice or more times. The script should use the lowest rows.
Here is the table that mySQL should output:
Number|Rows count to the end
16|7
7|1
86|2
49|5
47|0
36|3
The query should search columns n1, n2, n3, n4, n5 and pick the value most nearly to the end and count the remaining rows to the end.
Thanks ;)
Assuming your unnamed columns are named as follows:
c1 c2 c3 c4 c5 c6 c7 c8
18853 1945-01-05 BA 87 34 1 59 50
18854 1945-01-13 BA 6 66 1 16 48
18855 1945-01-20 BA 38 14 24 78 36
18856 1945-01-27 BA 49 30 87 15 65
18857 1945-02-03 BA 30 64 36 5 32
18858 1945-02-10 BA 15 36 37 86 31
18859 1945-02-17 BA 86 78 69 7 60
18860 1945-02-24 BA 83 7 72 88 19
18861 1945-03-03 BA 47 20 77 73 30
Furthermore assuming c1 is you PK index column and column c7 is the one you're interested in, following might give you what you want:
select t1.c7, MAX(t1.c1), (select count(*)
from table t2
where MAX(t1.c1) < t2.c1) as rowsToEnd
from table t1
group by t1.c7
Ok, after having supposedly understood what you want, the following should give you what you want:
EDIT: After having read Imre L's answer i realized i totally forgot about the IN operator, so this is the more elegant solution:
EDIT AGAIN: After having read your question update.
This is assuming that one of c4, c5, c6, c7, c8 contains all numbers that are occur in any one of those rows:
select distinct t3.c4, ( select count(*) AS RowsToEnd
from table t1
where t1.c1 > ( select max(t2.c1)
from table t2
where t3.c4 IN
(t2.c4, t2.c5, t2.c6, t2.c7, t2.c8)
)
from table t3
assuming the columns of numbers are names n1..n6
using 16 as the example number
select count(1)
from tablename
where date > (select date
from tablename
where 16 in (n1,n2,n3,n4,n5,n6)
order by date desc
limit 1)
what about reoccuring dates?