i need to get the next day time and date for library based on the following table in MySQL without using procedures
CREATE TABLE `library_timing` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`store_id` int(10),
`day` varchar(10) DEFAULT NULL,
`start_time` time DEFAULT NULL,
`end_time` time DEFAULT NULL,
PRIMARY KEY (`id`)
);
Insert into library_timing values(1,1,"Monday",'09:00:00','18:00:00');
Insert into library_timing values(2,1,"Tuesday",'09:00:00','18:00:00');
Insert into library_timing values(3,1,"Thrusday",'09:00:00','18:00:00');
Insert into library_timing values(4,1,"Friday",'09:00:00','18:00:00');
As u can see I have timings day for library
so the output expected is as follows
(Consider Today is MONDAY 25 June 2020)
ID. Next opening Time
1 26-06-2020 09:00:00
And (Consider if Today is TUESDAY 26 JUNE 2020 and WEDNESDAY IS HOLIDAY so DATE TIME FOR THURSDAY)
ID. Next opening Time
1 28-06-2020 09:00:00
i have tried this case so far which gives me next days time but not sure how to do if there is gap of more than 1 day
case
when
(curtime() < start_time or curtime() > end_time) or
(start_time = "00:00:00" and end_time = "00:00:00") or
(start_time is null and end_time is null)
then
UNIX_TIMESTAMP((
select TIMESTAMP(curdate()+1,(
select start_time
from library_timing a
where a.store_id = s.id and day = DAYNAME(CURDATE() + 1)
))
))
else 0 end nextopeningtime
I can advice next solution:
add column day_of_week for number day of week for simplify calcualtion:
CREATE TABLE `library_timing` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`store_id` INT(10),
`day_of_week` INT(10),
`day` VARCHAR(10) DEFAULT NULL,
`start_time` TIME DEFAULT NULL,
`end_time` TIME DEFAULT NULL,
PRIMARY KEY (`id`)
);
INSERT INTO library_timing VALUES(1,1,2,"Monday",'09:00:00','18:00:00');
INSERT INTO library_timing VALUES(2,1,3,"Tuesday",'09:00:00','18:00:00');
INSERT INTO library_timing VALUES(3,1,4,"Thrusday",'09:00:00','18:00:00');
INSERT INTO library_timing VALUES(4,1,5,"Friday",'09:00:00','18:00:00');
next we can use next approach:
SELECT * FROM (
-- check currently open
SELECT 'Open' , `lt`.*
FROM `library_timing` `lt`
WHERE
`lt`.`day_of_week` = DAYOFWEEK('2020-06-29') AND -- '2020-06-29' will be changed to CURRDATE()
CURTIME() BETWEEN `start_time` AND `end_time`
UNION
-- check open next day
SELECT * FROM (
SELECT 'Next' , `lt`.*
FROM `library_timing` `lt`
WHERE `lt`.`day_of_week` > DAYOFWEEK('2020-06-29') -- '2020-06-29' will be changed to CURRDATE()
LIMIT 1
) nextday
UNION
-- check first working day
SELECT 'Next' , `lt`.*
FROM `library_timing` `lt`
WHERE `lt`.`day_of_week` = 2
) opentime LIMIT 1;
This approach not ideal and can be improved
Related
I'm trying to count the records in my "records" table and insert in results table but I just want to count today's records.
Below you will see some alternatives that I tried (I'm using MySQL), but I keep getting this error:
You have a syntax error in your SQL next to '' on line 2
INSERT INTO results (Data,total)
VALUES (now(), (SELECT COUNT(*) FROM records WHERE Data = now());
This SQL also causes an error:
INSERT INTO results (Data, total)
VALUES (now(), (SELECT COUNT(record.ID) AS day FROM record
WHERE date(Data) = date(date_sub(now(), interval 0 day));
and then
INSERT INTO resultS (Data,total)
VALUES (now(), (SELECT COUNT(*) FROM records
WHERE Data >= DATE_SUB(CURRENT_DATE(), INTERVAL 1 DAY));
And yet another attempt:
INSERT INTO results (Data, Total)
VALUES (now(), (SELECT COUNT(*) FROM records
WHERE DATE(Data)= CURRENT_DATE() - INTERVAL 1 DAY));
This is my sql config man:
CREATE TABLE `records`
(
`ID` char(23) NOT NULL,
`Name` varchar(255) NOT NULL,
`Total` int(255) NOT NULL,
`Data` date NOT NULL,
`QrCode` varchar(255) NOT NULL,
`City` varchar(255) NOT NULL,
`Device` varchar(255) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE `results`
(
`id` int(11) NOT NULL,
`total` int(11) NOT NULL,
`Data` date DEFAULT NULL,
`grown` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
You have defined grown column as not null so you cannot put there NULL.
My query works :
INSERT INTO results
VALUES (1, (SELECT COUNT(1) FROM records WHERE Data= now()), now(), 1);
You should define default value for grown column. Same situation you have with column id. You should define sequence for column id:
id NOT NULL AUTO_INCREMENT;
INSERT INTO results (Data, total)
SELECT CURRENT_DATE(), COUNT(*)
FROM records
WHERE DATE(Data) = CURRENT_DATE();
I am working with agricultural product management system. I have a question regarding a MySQL query. I would like to know how to create the same query using Laravel query builder:
SELECT
vegitables.name, vegitables.image, vegitables.catagory,
AVG(price_wholesale),
SUM(CASE WHEN rank = 1 THEN price_wholesale ELSE 0 END) today,
SUM(CASE WHEN rank = 2 THEN price_wholesale ELSE 0 END) yesterday
FROM (
SELECT
veg_id, price_wholesale, price_date,
RANK() OVER (PARTITION BY veg_id ORDER BY price_date DESC) as rank
FROM old_veg_prices
) p
INNER JOIN vegitables ON p.veg_id = vegitables.id
WHERE rank in (1,2)
GROUP BY veg_id
This Output result get when run query in database:
Following two table are used to get today price yesterday price and price average get from each product.
CREATE TABLE `vegitables` (
`id` bigint(20) UNSIGNED NOT NULL,
`name` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
`image` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
`catagory` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
`total_area` int(11) NOT NULL COMMENT 'Total area of culativate in Sri Lanka (Ha)',
`total_producation` int(11) NOT NULL COMMENT 'Total production particular product(mt)',
`annual_crop_count` int(11) NOT NULL COMMENT 'how many time can crop pre year',
`short_dis` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`created_at` timestamp NULL DEFAULT NULL,
`updated_at` timestamp NULL DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
ALTER TABLE `vegitables`
ADD PRIMARY KEY (`id`);
ALTER TABLE `vegitables`
MODIFY `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=3;
COMMIT;
CREATE TABLE `old_veg_prices` (
`id` bigint(20) UNSIGNED NOT NULL,
`veg_id` int(11) NOT NULL,
`price_wholesale` double(8,2) NOT NULL,
`price_retial` double(8,2) NOT NULL,
`price_location` int(11) NOT NULL,
`price_date` date NOT NULL,
`created_at` timestamp NULL DEFAULT NULL,
`updated_at` timestamp NULL DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
ALTER TABLE `old_veg_prices`
ADD PRIMARY KEY (`id`);
ALTER TABLE `old_veg_prices`
MODIFY `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=6;
COMMIT;
I try this site to convert to MySQL query to query builder code. But it show some error's could find it out. Any Way i want to run this code in Laravel with any method??
Your query will not return the data for yesterday and today; it will return the data for two most recent dates (e.g. if today is 2021-11-01 and most recent two dates for for carrots are 2021-10-25 and 2021-10-20 it will use those two dates). Using RANK() ... IN (1, 2) is also incorrect because it can return ranks such as 1 followed by 3 instead of 2.
To get today and yesterday prices you don't need window functions. Just use appropriate where clause and conditional aggregation:
SELECT vegitables.name
, vegitables.image
, vegitables.catagory
, AVG(old_veg_prices.price_wholesale) AS avgwholesale
, SUM(CASE WHEN old_veg_prices.price_date = CURRENT_DATE - INTERVAL 1 DAY THEN old_veg_prices.price_wholesale END) AS yesterday
, SUM(CASE WHEN old_veg_prices.price_date = CURRENT_DATE THEN old_veg_prices.price_wholesale END) AS today
FROM vegitables
INNER JOIN old_veg_prices ON vegitables.id = old_veg_prices.veg_id
WHERE old_veg_prices.price_date IN (CURRENT_DATE - INTERVAL 1 DAY, CURRENT_DATE)
GROUP BY vegitables.id -- other columns from vegitables table are functionally dependent on primary key
The Laravel equivalent would be:
DB::table('vegitables')
->Join('old_veg_prices', 'old_veg_prices.veg_id', '=', 'vegitables.id')
->whereRaw('old_veg_prices.price_date IN (CURRENT_DATE - INTERVAL 1 DAY, CURRENT_DATE)')
->select(
'vegitables.name',
'vegitables.image',
'vegitables.catagory',
DB::raw('AVG(old_veg_prices.price_wholesale) AS avgwholesale'),
DB::raw('SUM(CASE WHEN old_veg_prices.price_date = CURRENT_DATE - INTERVAL 1 DAY THEN old_veg_prices.price_wholesale END) AS yesterday'),
DB::raw('SUM(CASE WHEN old_veg_prices.price_date = CURRENT_DATE THEN old_veg_prices.price_wholesale END) AS today')
)
->groupBy(
'vegitables.id',
'vegitables.name',
'vegitables.image',
'vegitables.catagory'
)
->get();
"Query builder" features of abstraction products often leave out some possible SQL constructs. I recommend you abandon the goal of reverse engineering SQL back to Laravel and simply perform the "raw" query.
Also...
rank() OVER (PARTITION BY veg_id ORDER BY price_date DESC) as rank
requires MySQL 8.0 (MariaDB 10.2).
And suggest you avoid the alias "rank" since that is identical to the name of a function.
i have 2 tables one library details and other is library timings
CREATE TABLE `library_details` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`library_name` varchar(100) DEFAULT NULL,
PRIMARY KEY (`id`);
INSERT INTO library_details VALUES(1,"library1");
CREATE TABLE `library_timing` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`library_id` int(11) DEFAULT NULL,
`start_time` time DEFAULT NULL,
`end_time` time DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `fk_library_timing_1` (`library_id`),
CONSTRAINT `fk_library_timing_1` FOREIGN KEY (`library_id`) REFERENCES `library_details` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1;
INSERT INTO library_timing VALUES(1,1,08:30,18:00);
i need to get the data as follows
----------------------------------
id | name | status | nextopentime |
-----------------------------------
1 | library1 | 0/1 | (could be in hrs)
status based on open close time 1 for open 0 for close
i can get the id and name using join but i am not sure how to calculate the other 2 fields
If I have understood your question correctly then maybe something like this would be what you are looking for:
select ld.id
, ld.library_name
, case when curtime() between lt.start_time and lt.end_time then
'1'
else
'0'
end "status"
, case when (curtime() - lt.end_time) > (curtime() - lt.start_time)
and curtime() not between lt.start_time and lt.end_time then
subtime(curtime() , lt.end_time)
when (curtime() - lt.end_time) < (curtime() - lt.start_time)
and curtime() not between lt.start_time and lt.end_time then
subtime( lt.start_time, curtime())
else
'00:00:00'
end "next open time"
from library_details ld
join library_timing lt on lt.id = ld.id;
here is a small demo
As you can see in my example if the library is open(status = 1) then the value in the column "next open time" will be 00:00:00.
If you want to add 24 hours you can do that like this:
addtime(subtime( lt.start_time, curtime()), "24:00:00")
I have a big log table in mariadb/mysql:
CREATE TABLE `logs` (
`id` CHAR(36) NOT NULL,
`user` CHAR(4) NOT, NULL,
`dateCreated` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
`dateUpdated` TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00',
PRIMARY KEY (`id`)
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB
I am trying to query logs based on user and date created by month and year:
select * from logs where month(dateCreated) = '9' and year(dateCreated) = '2016' and user = '1234'
Question:
Should I created two columns called month and year, and index the month, year, and user to speed up the query?
You are better off just restructuring your query's criteria to better take advantage of a possible index on the field:
WHERE dateCreated >= '2016-09-01 00:00:00'
AND dateCreated < '2016-10-01 00:00:00'
AND user = '1234'
Hello I have this table
TABLE `record` (
`zpravaID` int(11) NOT NULL AUTO_INCREMENT,
`sensorID` int(11) NOT NULL,
`date_time` datetime NOT NULL,
`cena` double DEFAULT NULL,
`is_cheap` tinyint(1) NOT NULL DEFAULT '0',
PRIMARY KEY (`zpravaID`), ...)
I would like to do an update which will for example take all records from 2016 and every record, which will be on Monday from 14:00:00 to 14:45:00 will have set the is_cheap to true (1).
I really have no idea, how to do that. Any ideas?
To extract the day of the week you can either use WEEKDAY() or DAYOFWEEK() , the difference between them is that in DAYOFWEEK() sunday is 1 . You can use DATE_FORMAT to extract only the time value, and YEAR() to extract the year of the date :
UPDATE `record` t
SET t.is_cheap = 1
WHERE DAYOFWEEK(t.date_time) = 2
AND DATE_FORMAT(t.date_time,'%H:%i:%s') BETWEEN '14:00:00' AND '14:45:00'
AND YEAR(t.date_time) = 2016
Try this:
update record
set is_cheap = 1
where YEAR(date_time) = 2016
and DAYNAME(date_time) = 'Monday'
and DATE_FORMAT(date_time,'%H:%i:%s') BETWEEN '14:00:00' AND '14:45:00'