i can not make aritmetic operation inside stored procedure mysql - mysql

there is an in parameter as page. all i want to do is expel 1 from it and multiply by 10. but it gives me an error every time.
IF !a THEN
SELECT *
from entry
WHERE topic_foreign_id = (
select topic_id
from topic
where topic_name = topicName
)
ORDER BY entry_time ASC
LIMIT 10 OFFSET page;
ELSE
SELECT *
from entry
WHERE topic_foreign_id = (
select topic_id
from topic
where topic_name = topicName
)
ORDER BY entry_time ASC;
END IF
this lines of code works great but when i want to make an aritmetic operation in first SQL query myAdmin throws an error everytime.
SELECT *
from entry
WHERE topic_foreign_id = (
select topic_id
from topic
where topic_name = topicName
)
ORDER BY entry_time ASC
LIMIT 10 OFFSET 10 * ( page - 1); //throws error

--- EDITED ---
LIMIT doesn't seem to like calculations. Try using a variable and use that value in your stored procedure
DECLARE v_page_offset INT DEFAULT 0;
SET v_page_offset = 10*(page-1);
Then later
LIMIT 10 OFFSET v_page_offset;

Related

UPDATE from SELECT but still return selected data in MySQL

I have read a bunch of ways that has gotten me this far. But I can't get to the finish line.
I have a table of coupon codes. I want to use one transaction to select the next available code, mark it as used and input the order number. I can get the update and nested select to work, but I cannot figure out how to actually return the coupon code from the select. It just returns 1 row updated.
Here's what I've got:
UPDATE `prcoupon` pr
SET
`pr`.`status` = '1',
`pr`.`invoicenumber` = '09990002'
WHERE
`pr`.`couponCode` = (SELECT
`prcoupon`.`couponcode`
FROM
`prcoupon`
WHERE
`status` = 0
LIMIT 1)
Sample data
What I need returned is: couponCode: SL2T-03A0-JVCY-W2XMXG
If I understand correctly, you can try to use UPDATE ... JOIN with ROW_Nunber windwon function.
UPDATE prcoupon pr
JOIN (
SELECT *,ROW_NUMBER() OVER(ORDER BY couponCode) rn
FROM prcoupon
WHERE status = 0
) t2 ON pr.couponcode = t2.couponcode
SET pr.status = 1,
pr.invoicenumber = '09990002'
WHERE rn = 1
sqlfiddle

Increment Row Index And Union With Other Tables On Dynamic Dates

Question:
I looked at various other examples to increment over rows, but all resulted in the same wrong output. The problem which I encountered was that my code did not successfully increment over rows to build a correct index per new row in the result-set per episode (highlighted in red below).
My first try was:
SET #ep_1 = "Peaky Blinders";
SET #curRow_1 = 0;
SELECT
DATE_FORMAT(created_at, "%Y%m%d") AS year_month_day,
#curRow_1 := #curRow_1 + 1 AS row_number,
#ep_1 AS episode_title,
COUNT(id) AS episode_plays
FROM netflix.episode_plays
WHERE
episode_id = "xyz"
AND created_at >= "2019-07-01" AND created_at <= "2019-07-07"
GROUP BY 1
Other than the rows not incrementing correctly; I also got the following error when I tried setting some variables in the beginning of my code:
Error running query: Illegal mix of collations (utf8_unicode_ci,IMPLICIT) and (utf8_general_ci,IMPLICIT) for operation '='
(Note: I have no affiliation with Netflix, I just used Netflix dummy data to answer my question)
I broke down my question in various sections and got to the final answer below.
The most important part was to add the initial result-sets into a subqueries, and thereafter select the data from tables x1,x2, etc.
The second part of the question was, how to combine multiple datasets together (in my case: how do one not only do it for one specific netflix episode, but multiple episodes)? I settled on the UNION ALL - clause.
In the first iteration I tried hard-coding the dates, and thereafter found the INTERVAL-function very helpful.
Finally, the unicode-error I fixed by adding COLLATE utf8_unicode_ci after setting my variables.
If you find mistakes in my code or have any other suggestions, please feel free to suggest them.
-- SET DATA
-- variables for table x1
SET #ep_1 = "Peaky Blinders" COLLATE utf8_unicode_ci;
SET #id_1 = (SELECT id FROM netflix.episodes WHERE episode_title = #ep_1);
SET #date_1 = (SELECT created_at FROM netflix.episodes WHERE episode_title = #ep_1);
SET #curRow_1 = 0;
-- variables for table x2
SET #ep_2 = "Brooklyn Nine-Nine" COLLATE utf8_unicode_ci;
SET #id_2 = (SELECT id FROM netflix.episodes WHERE episode_title = #ep_2);
SET #date_2 = (SELECT created_at FROM netflix.episodes WHERE episode_title = #ep_2);
SET #curRow_2 = 0;
-- QUERY DATA
SELECT
x1.year_month_day,
#curRow_1 := #curRow_1 + 1 AS row_number,
x1.episode_title,
x1.episode_plays
FROM (
SELECT
DATE_FORMAT(created_at, "%Y%m%d") AS year_month_day,
#ep_1 AS episode_title,
COUNT(id) AS episode_plays
FROM netflix.episode_plays
WHERE
episode_id = #id_1
AND created_at >= #date_1 AND created_at <= DATE_ADD(#date_1 , INTERVAL 7 DAY)
GROUP BY 1) x1
UNION ALL
SELECT
x2.year_month_day,
#curRow_2 := #curRow_2 + 1 AS row_number,
x2.episode_title,
x2.episode_plays
FROM (
SELECT
DATE_FORMAT(created_at, "%Y%m%d") AS year_month_day,
#ep_2 AS episode_title,
COUNT(id) AS episode_plays
FROM netflix.episode_plays
WHERE
episode_id = #id_2
AND created_at >= #date_2 AND created_at <= DATE_ADD(#date_2 , INTERVAL 7 DAY)
GROUP BY 1) x2

Simplify sql query to obtain one line per id

I have a multi-table SQL query.
My need is: The query should I generate a single line by 'etablissement_id' ... and all information that I want to be back in the same query.
The problem is that this query is currently on a table where "establishment" may have "multiple photos" and suddenly, my query I currently generates several lines for the same id...
I want the following statement - LEFT JOINetablissementContenuMultimediaON etablissement.etablissement_id = etablissementContenuMultimedia.etablissementContenuMultimedia_etablissementId - only a single multimedia content is displayed. Is it possible to do this in the query below?
Here is the generated query.
SELECT DISTINCT `etablissement`. * , `etablissementContenuMultimedia`. * , `misEnAvant`. * , `quartier`. *
FROM `etablissement`
LEFT JOIN `etablissementContenuMultimedia` ON etablissement.etablissement_id = etablissementContenuMultimedia.etablissementContenuMultimedia_etablissementId
LEFT JOIN `misEnAvant` ON misEnAvant.misEnAvant_etablissementId = etablissement.etablissement_id
LEFT JOIN `quartier` ON quartier_id = etablissement_quartierId
WHERE (
misEnAvant_typeMisEnAvantId =1
AND (
misEnAvant_dateDebut <= CURRENT_DATE
AND CURRENT_DATE <= misEnAvant_dateFin
)
)
AND (
etablissement_isActive =1
)
ORDER BY `etablissement`.`etablissement_id` ASC
LIMIT 0 , 30
Here is the code used ZF
public function find (){
$db = Zend_Db_Table::getDefaultAdapter();
$oSelect = $db->select();
$oSelect->distinct()
->from('etablissement')
->joinLeft('etablissementContenuMultimedia', 'etablissement.etablissement_id = etablissementContenuMultimedia.etablissementContenuMultimedia_etablissementId')
->joinLeft('misEnAvant', 'misEnAvant.misEnAvant_etablissementId = etablissement.etablissement_id')
->joinLeft('quartier', 'quartier_id = etablissement_quartierId ')
->where ('misEnAvant_typeMisEnAvantId = 1 AND (misEnAvant_dateDebut <= CURRENT_DATE AND CURRENT_DATE <= misEnAvant_dateFin) ')
->where ('etablissement_isActive = 1')
->order(new Zend_Db_Expr('RAND()'));
$zSql = $oSelect->__toString();
if(isset($_GET['debug']) AND $_GET['debug'] == 1)
echo $zSql ;
//die();
$oResultEtablissement = $db->fetchAll($oSelect);
return $oResultEtablissement ;
}
Can you help me?
Sincerely,
If you are looking to have only one of the media displayed out of many regardless of which it may be then you can just add a limit to the query? After that you can tweak the query for ASCending or DESCending perhaps?
Is this query supposed to have images (or image as it were) for one establishment, or one image each for each active establishment? I see you have a limit 0,30 which means you're likely paginating....
If the result you want is a search for only one establishment, and the first image it comes to would work fine .. just use "limit 1" and you'll only get one result.
I took the time to redo the whole model of the database ... and now it works. There was no solution for a system as flawed

MySQL select all entries between two dates regardless of year

I need to find all rows in a MySQL database that fall between "YYYY-10-30" and "YYYY-12-11" I don't care about which year the the date is in just that falls between the two dates.
SELECT *
FROM yourTable
WHERE (MONTH(yourDate) = 10 AND DAYOFMONTH(yourDate) >= 30)
OR (MONTH(yourDate) = 11)
OR (MONTH(yourDate) = 12 AND DAYOFMONTH(yourDate) <= 11)
select *
from table
where
concat(year(now()),right(date_field,6))
between
concat(year(now()),'-10-30')
and
concat(year(now()),'-12-11')
Could you try this?:
CREATE DEFINER=`root`#`localhost` PROCEDURE `GetByMonthAndDayRange`
(
IN monthFrom INT
, IN dayFrom INT
, IN monthTo INT
, IN dayTo INT
)
BEGIN
-- For good coding practice, name your columns instead of using *
SELECT *
FROM tablename
WHERE
(MONTH(datecolumnname) = monthFrom AND DAYOFMONTH(datecolumnname) >= dayFrom)
OR (MONTH(datecolumnname) > monthFrom AND MONTH(datecolumnname) < monthTo)
OR (MONTH(datecolumnname) = monthTo AND DAYOFMONTH(datecolumnname) <= dayTo);
END
If you use a stored procedure (and if the code works to your taste) you'll be able to code faster, just providing the parameters (it's dynamic this way)

grouping by non-database field

How can I group a query result by a field that is not saved in the database.
For example I want to group the result by duration which is came from subtraction of start time and end time.
here is how i find out the duration
date1= $row_TicketRS['CloseDate'];
$date2 = $row_TicketRS['OpenDate'];
$diff = abs(strtotime($date2) - strtotime($date1));
$days = floor(($diff - $years * 365*60*60*24 - $months*30*60*60*24)/ (60*60*24));
if ( $days > 0)
{
$time1 = $row_TicketRS['OpenTime'];
$time2= $row_TicketRS['CloseTime'];
$t1=($time1);
$t2=($time2);
$end=('14:30');
$start=('07:30');
$n = $end- $t1;
$n2 = $t2- $start;
$Hours2 = floor(($n+$n2)+(($days-1)*7));
echo $Hours2.' Hours';
but know i do not know how to add it to the query
here is my query
$strQuery = "SELECT count(`ticket`.TicketID) as TotOutput, department.`DeptName` FROM `ticket`, `user`, department where ticket.OwnerID = user.EmpNo and user.`DepartmentID` = department.`DepartmentID` and OpenDate between'".$DateFrom."' And '".$DateTo."'"
It'd be better to have details, but a derived table/inline view would allow you to group by a computed value:
SELECT x.duration,
COUNT(*)
FROM (SELECT t.col,
t.end_time - t.start_time AS duration
FROM YOUR_TABLE t) x
GROUP BY x.duration
How about adding that computed value to the query with an alias like this:
SELECT some_fields, end - start AS duration FROM table ORDER BY duration
dont put alias for hidden column , use directly
exmaple:
SELECT id, FLOOR(value/100)
FROM tbl_name
GROUP BY id, FLOOR(value/100);
Reference
MySQL permits expressions in GROUP BY
clauses, so the alias is unnecessary: