Backfill data using coalesce - mysql

I am trying to backfill data using a coalesce function, alongside first_value and last_value functions, however the records do not seem to be populating.
In the example picture, I would like the cellphone number 033333333 to be populated from that row until the 0444444444 record row, and then to have the 0444444444 value persist until the end , or until if there were a new value eg.05555555555.
This is the code that I have tried running, however it has had no effect on the output.
,CASE WHEN Contact_RowNum = 1 AND dim_active = 0 AND Contact_CellPhoneNumber IS NULL THEN NULL
WHEN Contact_RowNum = 1 and dim_active in(0,1) THEN Contact_CellPhoneNumber
WHEN Contact_RowNum IS NULL OR Contact_RowNum !=1 THEN
coalesce
(
last_value(Contact_CellPhoneNumber) over (PARTITION BY InvolvedPartyId,dim_Active order by RecordValidityStartDate desc ),
first_value(Contact_CellPhoneNumber) over (PARTITION BY InvolvedPartyId,dim_Active order by RecordValidityStartDate desc
RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING
)
)

Related

How to get the newest record without using limit in MYSQL

I have a MySQL script to find out the newest record, but it fails to get the incorrect result. I am giving the SQL script below:
SELECT
adjust_after,
spu_code,
sku_code,
store_id,
create_time
FROM
goods_store_stock_update_record
WHERE
is_del = 0
AND create_time >= DATE '2021-05-26'
AND create_time <= DATE '2021-05-27'
AND store_id = '18cc1cc715774d0196d17420c5104c15'
AND sku_code = 'SKUH201900001202050004' HAVING MAX(create_time)
There is a result without Having max(create_time):
"adjust_after" "spu_code" "sku_code" "store_id" "create_time"
"8" "SPH201900001202050001" "SKUH201900001202050004" "18cc1cc715774d0196d17420c5104c15" "26/5/2021 11:29:20"
"7" "SPH201900001202050001" "SKUH201900001202050004" "18cc1cc715774d0196d17420c5104c15" "26/5/2021 11:35:14"
But, when I am trying to query the create_time that was the newest:2021-05-26 11:35:14 record using having max(create_time). Unfortunately, It returns the incorrect record below:
8 SPH201900001202050001 SKUH201900001202050004 18cc1cc715774d0196d17420c5104c15 2021-05-26 11:29:20
Therefore, in this situation, how can I correct the querying script without using order by create_time and limit one.
Best regards. I really appreciate it.
There are two main mistakes in your query.
First, HAVING wants a boolean expression, just like WHERE. MAX(create_time) is not a boolean, but a datetime. What MySQL does here is convert the datetime to a number (maybe the internal representation of that datetime) and the number to a boolean (where 0 = false and everything else = true). So, that expression will result in true for about every row.
Second, MAX(create_time) is an aggregation. Without a GROUP BYclause this results in a single row. adjust_after etc. however, are not aggregated. This should result in a syntax error, but MySQL applies ANY_VALUE instead. This means you are telling MySQL, to give you one of the adjust_after that it finds, one of the spu_code, etc., all arbitrarily picked.
The straight-forward solution would be ORDER BY create_time LIMIT 1, which you don't want for reasons unknown to us.
Another solution is
SELECT
adjust_after,
spu_code,
sku_code,
store_id,
create_time
FROM goods_store_stock_update_record
WHERE is_del = 0
AND store_id = '18cc1cc715774d0196d17420c5104c15'
AND sku_code = 'SKUH201900001202050004' HAVING MAX(create_time)
AND create_time =
(
SELECT MAX(create_time)
FROM goods_store_stock_update_record
WHERE is_del = 0
AND create_time >= DATE '2021-05-26'
AND create_time <= DATE '2021-05-27'
AND store_id = '18cc1cc715774d0196d17420c5104c15'
AND sku_code = 'SKUH201900001202050004'
);

MySQL Display 4th smallest value for each team

I am using phpMyAdmin on MySQL 5.7
The code below selects the lowest values excluding any zero values and gives me a nice table of all the teamids with the lowest times in seconds next to them for that event (zid).
SELECT teamid, MIN(time) AS 'fastest time'
FROM data
WHERE time > 0 AND zid = 217456
GROUP BY teamid
How do I adapt it to get the 4th lowest values?
I have tried countless suggestions found via searching but none work
Table Headings:
id (AI column set as Primary Index)
zid (this is an event identification number)
teamid
name
time (given in seconds)
I could add a position in team column which would make this very easy? Then I just ask MySQL to get me all the positions = to 4 ?
MySQL 8: Use Window functions.
Dense Rank
Window Function Concept & Syntax
SELECT
teamid,
time '4th_Lowest'
FROM data
WHERE time > 0 AND zid = 217456
AND (dense_rank() OVER (PARTITION BY teamid ORDER BY time ASC)) = 4;
Mysql 5.7 and Lower: We will use following variables to calculate this on the sorted data(teamid and then time)
rank - to set rank for each unique(teamid, time)
c_time - whenever there is a change between time of two consecutive rows, we will increase the rank. IF(#c_time = d.time, #rank, #rank:= #rank + 1)
c_team_id - we will check whether two consecutive rows have same or different team, if different then reset rank to 1. Check else part IF(#c_team_id = d.teamid, ...,#rank:= 1)
SELECT
t.teamid,
t.`time`
FROM(
SELECT
d.teamid, -- Represent current row team id
d.`time`, -- Represent current row time
IF(#c_team_id = d.teamid, IF(#c_time = d.`time`, #rank, #rank:= #rank + 1), #rank:= 1) as rank, -- determine rank based on above explanation.
#c_team_id:= d.teamid, -- We are setting this variable to current row team id after using it in rank column, so rank column of next row will have this row team id for comparison using #c_team_id variable.
#c_time:= d.`time`
FROM `data` AS d,
(SELECT #c_time:= 0 as tim, #c_team_id:= 0 as tm_id, #rank:= 0 as rnk) AS t
WHERE d.`time` > 0 AND d.zid = 217456
ORDER BY d.teamid, d.`time` ASC -- Use to make sure we have same team records in sequence and with ascending order of time.
) AS t
WHERE t.rank = 4
GROUP BY t.teamid;
If your version supports window-functions (since 8.0):
SELECT teamid, time 'fourth_time'
FROM data
WHERE time > 0
AND zid = 217456
AND (dense_rank() OVER (PARTITION BY teamid ORDER BY time ASC)) = 4
EDIT: dense_rank seems to fit better, it will give the fourth-best time now, ignoring multiple appearances of the best to third-best times. The earlier version used row_number, not ignoring multiple apperances. Thanks for mentioning in the comments.
Since your version does not support window-functions, you can use a subselect with a LIMIT (I assume you have a field id, that is a primary key. If your primary key is another field, just replace this. If there is more than one field in your primary key, you will need to check all of them):
SELECT d.teamid, MIN(d.time) fourth_time
FROM data d
WHERE d.time > 0
AND d.zid = 217456
AND d.time > (SELECT t.time
FROM ( SELECT DISTINCT d2.time
FROM data d2
WHERE d2.time > 0
AND d2.zid = 217456
AND d2.teamid = d.teamid
) t
ORDER BY t.time ASC
LIMIT 1
OFFSET 2)
GROUP BY d.teamid

Count Distinct Date MySQL returning one row

Ok so be ready I'm working on a weird base :
Every table has 3 column only : varchar('Object'),varchar('Property'),varchar('Value')
Here is a fiddle I've build with examples of my tries
http://sqlfiddle.com/#!9/de22eb/1
I need to extract the last time a server was update. But i'm not interested in the server itself it's more about the date. Once I know that there was an update for a date I'm looking to count every updates on that day.
To do so I'm using 2 tables : the server table
CREATE TABLE IF NOT EXISTS `server` (
`name` varchar(80) NOT NULL,
`field` varchar(80) NOT NULL,
`value` varchar(200) NOT NULL
);
And the event table :
CREATE TABLE IF NOT EXISTS `event` (
`name` varchar(80) NOT NULL,
`field` varchar(80) NOT NULL,
`value` varchar(80) NOT NULL
);
Please go watch the fiddle to have an idea of the content.
I want to have a result like this (based on my example) :
Date Number patched
2017-11-14 2
2017-11-04 1
The problem is that I don't know where I'm wrong on my query (I've separated the step for better understanding inside the fiddle) :
Select date_format(d.val, '%Y-%m-%d') as 'Date', COUNT(distinct
date_format(d.val, '%Y-%m-%d')) as 'Number'
FROM (
Select b.serv,b.val
FROM (
Select serv,val FROM (
Select name as serv, value as val FROM event
where field='server_vers' and
value!='None'
order by serv ASC,
val DESC LIMIT 18446744073709551615) a
group by a.serv) b,
server c
where b.serv = c.name and c.field = 'OS' and c.value = 'Fedora'
) d group by date_format(d.val, '%Y-%m-%d');
It's giving me only one row. Adding group by date_format(d.val, '%Y-%m-%d') at the end makes the Count useless. How can I fix that ?
I want to have for each server for a given OS type the last patch date and then sum the result by date.
Is that what you needed ?
SELECT dates.date, COUNT(dates.date) as patch_count
FROM (
SELECT MAX(date_format(event.value, '%Y-%m-%d')) as date
FROM event
JOIN server ON (event.name = server.name)
WHERE (server.field = 'OS' AND server.value = 'Fedora')
GROUP BY event.name ) as dates
GROUP BY 1
ORDER BY 2 DESC
Here's the fiddle :
http://sqlfiddle.com/#!9/de22eb/37/0
Explanation : We get the last date for every server name. That gives a list of last dates. Then we use this as a table, that we can group on to count each different value.
The datetimes are stored as strings. The first ten characters of that string represent the date. So you get the date with left(value, 10).
You get the last update per server by grouping by server and retrieving max(left(value, 10)), because alphabetic order works on 'yyyy-mm-dd'.
select name, max(left(value, 10))
from event
where field = 'server_vers'
and value <> 'None'
group by name
Build up on this to get the count of updates on those last-update dates:
select left(value, 10), count(*)
from event
where field = 'server_vers'
and left(value, 10) in
(
select max(left(value, 10))
from event
where field = 'server_vers'
and value <> 'None'
group by name
)
group by left(value, 10)
order by left(value, 10);

Cyclical update in the same table - complementary

Respected all,
I have the following query that is executed only for a date by the filter that is noted, what I need is to run for all the dates in the table, and I can not find the way to indicate that function, I appreciate its special orientation:
update scraper_data_twitter as T1,
(
select Ntweets as Ntweets_var,
(
select COUNT(Ntweets) + 1
from scraper_data_twitter
where (NTweets > Ntweets_var)
and date = '2017-02-13'
) as rank
from scraper_data_twitter
where date = '2017-02-13'
group by SITE,
date
order by NTweets_var desc
) as A
set T1.rnk_Ntweets = A.rank
where T1.ntweets = A.Ntweets_var

Order By is a case with ascending and decending orders

I am using MySQL database. I have to make a stored procedure which accepts an integer type parameter. Depending upon the integer's value i have to 'order by' a different value like this..
**if(type == 1) than
order by Date Desc,
Quantity asc,
Amount asc
else if(type == 2)than
order by Date ASc,
Quantity asc,
Amount asc
else if(type == 3)than
order by
Quantity asc
Date desc,
Amount asc
However when i try this i am unable to do this its gives error also.
If you look at the syntax for SELECT, you'll see that the ORDER BY clause can't appear within a CASE statement.
If a column is a numeric type, you can write an expression that is 1 for ascending, -1 for descending and multiply the expression by the column to sort by, though this will impact performance as MySQL won't be able to use any indices for the sort.
SELECT ...
ORDER BY IF(?='d', -1, 1) * value
In general however, you'll have to use different statements to get different orderings.
If Date is a proper date or datetime you can do something like this:
ORDER BY
CASE type WHEN 3 THEN -1 * Date ELSE Date END asc,
Quantity asc, Amount asc
http://dev.mysql.com/doc/refman/5.0/en/case-statement.html
This works because date, time and the other MySQL date and time types are stored internally as integers:
http://dev.mysql.com/doc/refman/5.0/en/storage-requirements.html
Well i got the solution finally....
SELECT distinct
order_detail.*, -(1)*CAST(order_detail.Date as unsigned) as lOrderDate,
from order_detail
order by
CASE
WHEN type = 1 THEN lOrderDate
WHEN type = 2 THEN order_detail.Date
WHEN type = 3 THEN order_detail.Quantity
END,
CASE
WHEN type = 1 THEN order_detail.Quantity
WHEN type = 2 THEN order_detail.Quantity
WHEN type = 3 THEN lOrderDate
END,
CASE
WHEN type = 1 THEN order_detail.Amount
WHEN type = 2 THEN order_detail.Amount
WHEN type = 3 THEN order_detail.Amount
END;
Two ways:
Build your query - like a string, then use a prepared statements to execute it.
Use IF-ELSEIF-END IF statement to execute three different SELECT queries.