I have data with begin and end date, sometimes the end date had a null and is now
'0000-00-00'
I have a query that says:
UPDATE w_preletter as L INNER JOIN w_prov_sensitive AS P ON L.IRS_TAX_ID = P.TAX_ID
set L.sensitive_provider = '1', L.OFFSET_RESTRICTED = P.OFFSET_RESTRICTED
where L.DATE_OF_SERVICE_BEG between P.BEGIN_DATE AND P.END_DATE;
but if the date is '0000-00-00' it means it is still effective so I need it to temporarily consider it the sysdate , otherwise it will not consider the date being in between. what would the syntax be for that?
I don't know if its a case statement and if so how I would write it out.
try this
UPDATE w_preletter as L INNER JOIN w_prov_sensitive AS P ON L.IRS_TAX_ID = P.TAX_ID
set L.sensitive_provider = '1', L.OFFSET_RESTRICTED = P.OFFSET_RESTRICTED
where L.DATE_OF_SERVICE_BEG between P.BEGIN_DATE AND P.END_DATE
or (L.DATE_OF_SERVICE_BEG >= P.BEGIN_DATE AND P.END_DATE = '0000-00-00')
Create a temporary table containing all the rows in w_prov_sensitive (CREATE TABLE ... SELECT syntax)
update the temporary table setting all END_DATE's to NOW() if they are 0/NULL/whatever
Do the UPDATE by joining against the temporary table
You could also put boolean logic to work and use a convoluted WHERE clause.
where
( P.END_DATE != 0 and L.DATE_OF_SERVICE_BEG between P.BEGIN_DATE AND P.END_DATE )
OR ( P.END_DATE = 0 and L.DATE_OF_SERVICE_BEG between P.BEGIN_DATE AND NOW() )
Related
update
table1 a
inner join table2 b on a.unique_id = b.unique_id
set
a.menu_return = sum(
case when b.value1 = 'mainmenu'
and b.value2 = '0' then 1 else 0 end
)
where
a.time_stamp >= '2021-12-17 00:00:00'
and a.time_stamp < '2021-12-18 00:00:00';
ERROR 1111 (HY000): Invalid use of group function
What cause this issue?
I'm not really understand what you try to achieve by this query, but looks as you need to use join with pre-aggregated query like:
update table1 a
inner join (
select
unique_id,
sum( case when value1 = 'mainmenu' and value2 = '0' then 1 else 0 end ) menu_return
from table2
group by unique_id
) b on a.unique_id = b.unique_id
set
a.menu_return = b.menu_return
where
a.time_stamp >= '2021-12-17 00:00:00' and a.time_stamp < '2021-12-18 00:00:00';
You can play with MySQL online here
I have the following query:
UPDATE pc
INNER JOIN cams
ON cams.cam_id = pc.camuid
SET
timestamp = NOW(),
uid = #out_param:=uid
WHERE zone = 1
AND (unable = '0' OR unable IS NULL)
AND (corrected_plate = '' OR corrected_plate IS NULL)
AND (timestamp IS NULL OR timestamp < (NOW() - INTERVAL #interval MINUTE))
LIMIT 1;
SELECT #out_param;
I am unable to run that query as I have a LIMITclause in a join query. I cannot figure out how to spread it out into a subquery while maintaining performance. I need this query to be as fast as possible, and the optimiser of MySQL has not provided much help so far.
This is the error obtained from MySQL, as the above is not allowed: Incorrect usage of UPDATE and LIMIT
Just use a subquery to decide which uid update.
UPDATE PC
SET timestamp = NOW(),
uid = #out_param:=uid
WHERE uid = (SELECT uid
FROM ( SELECT * FROM pc ) as pc2
INNER JOIN cams
ON cams.cam_id = pc2.camuid
WHERE zone = 1
AND (unable = '0' OR unable IS NULL)
AND (corrected_plate = '' OR corrected_plate IS NULL)
AND (timestamp IS NULL OR timestamp < (NOW() - INTERVAL #interval MINUTE))
ORDER BY uid -- optional
LIMIT 1)
How i can fill date gaps in MySQL? Here is my query:
SELECT DATE(posted_at) AS date,
COUNT(*) AS total,
SUM(attitude = 'positive') AS positive,
SUM(attitude = 'neutral') AS neutral,
SUM(attitude = 'negative') AS negative
FROM `messages`
WHERE (`messages`.brand_id = 1)
AND (`messages`.`spam` = 0
AND `messages`.`duplicate` = 0
AND `messages`.`ignore` = 0)
GROUP BY date ORDER BY date
It returns proper result set - but i want to fill gaps between dates start and end by zeros. How i can do this?
You'll need to create a helper table and fill it with all dates from start to end, then just LEFT JOIN with that table:
SELECT d.dt AS date,
COUNT(*) AS total,
SUM(attitude = 'positive') AS positive,
SUM(attitude = 'neutral') AS neutral,
SUM(attitude = 'negative') AS negative
FROM dates d
LEFT JOIN
messages m
ON m.posted_at >= d.dt
AND m.posted_at < d.dt + INTERVAL 1 DAYS
AND spam = 0
AND duplicate = 0
AND ignore = 0
GROUP BY
d.dt
ORDER BY
d.dt
Basically, what you need here is a dummy rowsource.
MySQL is the only major system which lacks a way to generate it.
PostgreSQL implements a special function generate_series to do that, while Oracle and SQL Server can use recursion (CONNECT BY and recursive CTEs, accordingly).
I don't know whether MySQL will support the following/similar syntax; but if not, then you could just create and drop a temporary table.
--Inputs
declare #FromDate datetime, /*Inclusive*/
#ToDate datetime /*Inclusive*/
set #FromDate = '20091101'
set #ToDate = '20091130'
--Query
declare #Dates table (
DateValue datetime NOT NULL
)
set NOCOUNT ON
while #FromDate <= #ToDate /*Inclusive*/
begin
insert into #Dates(DateValue) values(#FromDate)
set #FromDate = #FromDate + 1
end
set NOCOUNT OFF
select dates.DateValue,
Col1...
from #Dates dates
left outer join SourceTableOrView data on
data.DateValue >= dates.DateValue
and data.DateValue < dates.DateValue + 1 /*NB: Exclusive*/
where ...?
I am trying to optimize this query. Now it takes 28 seconds.
AS used to be missing in my query. After adding, query time dropped 20%
SELECT
g.id,
g.adresid,
g.senaryoid,
g.olayid,
g.gonderilecegitarih
FROM
(
SELECT
adresid
FROM
expose2.800_emsenaryolar_emgidenbulten
WHERE
olayid = '3320'
) AS s
RIGHT JOIN expose2.800_emsenaryolar_emgidenbulten AS g ON s.adresid = g.adresid
WHERE
s.adresid IS NULL
AND g.olayid = '2784'
AND g.durum = '1'
AND g.gonderilecegitarih < DATE_SUB(
'2015-05-13 15:40:15',
INTERVAL 1 DAY
)
If you use s.adresid IS NULL condition in subquery it will join faster then more rows ...
SELECT
g.id,
g.adresid,
g.senaryoid,
g.olayid,
g.gonderilecegitarih
FROM (
SELECT adresid FROM expose2.800_emsenaryolar_emgidenbulten WHERE olayid = '3320' and s.adresid IS NULL
) AS s
RIGHT JOIN expose2.800_emsenaryolar_emgidenbulten AS g ON s.adresid = g.adresid
AND g.olayid = '2784'
AND g.durum = '1'
AND g.gonderilecegitarih < DATE_SUB(
'2015-05-13 15:40:15',
INTERVAL 1 DAY
)
still this query optimized using self join.
For added speed, add this composite index to g:
INDEX(olayid, durum, gonderilecegitarih)
Please provide SHOW CREATE TABLE 800_emsenaryolar_emgidenbulten; I want to verify that you also have an index on adresid.
Update a single column over multiple rows depending on the data from the same table.
update table1 set status=newtime
from (
select
case
when TIME_FORMAT( TIMEDIFF( ADDTIME( time_val, '120:00:00' ), NOW() ), '%Hh %im %ss')<0 then '4'
else '0'
end as newtime,
id as new_id
FROM table1
where id2='2'
and status='0'
)
where id=new_id
This is my query. Thanks in advance.
Edit:
This is an alternate query to achieve this. But it also gives me an error
update table1 set status=
(select
case when timeleft<0 then '4' else '0' end as something,
new_id
from
(
select
TIME_FORMAT( TIMEDIFF( ADDTIME( time_val, '120:00:00' ), NOW() ), '%Hh %im %ss') as newtime,
id as new_id
FROM
table1
where id2='2' and
status='0'
)
}
where id=new_id
"#1248 - Every derived table must have its own alias".
I cannot use alias as I am fetching two columns from the query. Any help would be great.
UPDATE statements have no FROM clause in MySQL syntax. However, you can JOIN table against the subquery.
UPDATE
table1 t1
JOIN (
select
case
when TIME_FORMAT( TIMEDIFF( ADDTIME( time_val, '120:00:00' ), NOW() ), '%Hh %im %ss')<0 then '4'
else '0'
end as newtime,
id as new_id
FROM table1
WHERE id2='2' AND status='0'
) tsub ON t1.id = tsub.new_id
SET status = tsub.newtime
It looks to me like you don't need to do any subquerying or joining at all. This should do what you want:
UPDATE table1
SET status = CASE WHEN TIME_FORMAT(TIMEDIFF(ADDTIME(time_val, '120:00:00'), NOW()), '%Hh %im %ss') < 0 THEN '4' ELSE '0' END
WHERE id2 = '2' AND status = '0'
In the query you wrote, your subquery will get back the new time_val and the id number of the row to update, for any rows that match the criteria id2 = '2' AND status = '0'. You will then update all those rows (that matched the above criteria) and set the status to the new time_val.
Instead of selecting them first, cut out the middle man and just update all rows that match that criteria with the new value. Your query will be faster and more straightforward.
Besides the simplified version (provided by #Travesty3), it seems you are using a whole bunch of date and time functions to test for a simple thing:
UPDATE table1
SET status = '4'
WHERE id2 = '2'
AND status = '0'
AND time_val < NOW() - INTERVAL 120 HOUR
We can update table with multiple row by same table or two different table in this manner, just posting a snippet of mysql code from my procedure
Update documentcolumns as tb1, documentcolumns as tb2 set tb1.documentColumnPos = tb2.documentColumnPos Where tb1.userID = user_id and tb2.userID is NULL and tb1.columnNameDefID= tb2.columnNameDefID and tb1.tabtype = tab_type and tb2.tabtype = tab_type;,