I have a question for which I do not know how exactly to call it. Maybe I just don't use the correct naming and therefore I cannot find the answer.
But the case is like this.
I have a database table with similair data to the following:
booking_id (int)
booking_start (Y-m-d)
booking_starttime (H:i)
booking_hotelstart (Y-m-d)
booking_hotelstarttime (Y-m-d)
booking_hotelend (Y-m-d)
booking_hotelendtime (H:i)
booking_end (Y-m-d)
booking_endtime (H:i)
booking_confirmed (bool)
Now I would like to make a query that does about this :
(invalid query just to demonstrate what I would like)
SELECT `booking_id` FROM `system_bookings` WHERE (
(`booking_start`='2014-10-20' ORDER BY `booking_starttime` ASC)
OR
(`booking_hotelstart`='2014-10-20' ORDER BY `booking_hotelstarttime` ASC)
OR
(`booking_hotelend`='2014-10-20' ORDER BY `booking_endtime` ASC)
OR
(`booking_end`='2014-10-20' ORDER BY `booking_endtime` ASC)
)
AND
`booking_confirmed` = TRUE LIMIT 0, 100
So basically an ORDER BY with a clause. But how to do this?? I have no clue how to correctly search for this. Hence I hope someone could show me a bit the direction I should be heading. Other than that. I would like to know how this is called. For next searches.
Thanx in advance!!!
edit :
I created some sample data as requested :
CREATE TABLE IF NOT EXISTS `system_bookings` (
`booking_id` int(6) NOT NULL AUTO_INCREMENT,
`booking_start` date NOT NULL,
`booking_starttime` varchar(5) NOT NULL,
`booking_hotelstart` date NOT NULL,
`booking_hotelstarttime` varchar(5) NOT NULL,
`booking_hotelend` date NOT NULL,
`booking_hotelendtime` varchar(5) NOT NULL,
`booking_end` date NOT NULL,
`booking_endtime` varchar(5) NOT NULL,
`booking_confirmed` tinyint(1) NOT NULL,
PRIMARY KEY (`booking_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=6 ;
INSERT INTO `system_bookings` (`booking_id`, `booking_start`, `booking_starttime`, `booking_hotelstart`, `booking_hotelstarttime`, `booking_hotelend`, `booking_hotelendtime`, `booking_end`, `booking_endtime`, `booking_confirmed`) VALUES
(1, '2014-10-09', '21:19', '2014-10-08', '21:19', '2014-10-23', '08:00', '2014-10-23', '22:00', 1),
(2, '2014-10-11', '16:00', '2014-10-27', '12:15', '2014-10-28', '17:45', '2014-10-28', '17:45', 1),
(3, '2014-10-10', '20:30', '2014-10-10', '20:30', '2014-10-11', '08:00', '2014-10-20', '14:00', 1),
(4, '2014-10-12', '20:00', '2014-10-12', '20:00', '2014-10-13', '05:00', '2014-10-29', '22:00', 0),
(5, '2014-10-22', '15:00', '2014-10-22', '20:30', '2014-10-23', '04:15', '2014-10-31', '12:00', 1);
You can have multiple conditions in the order by clause. So, formally, you seem to want this:
SELECT `booking_id`
FROM `system_bookings`
WHERE `booking_confirmed` = TRUE AND
(`booking_start` = '2014-10-20' OR
`booking_hotelstart` = '2014-10-20' OR
`booking_hotelend`='2014-10-20' OR
`booking_end`='2014-10-20'
)
ORDER BY (CASE WHEN `booking_start` = '2014-10-20' THEN `booking_starttime`
WHEN `booking_hotelstart` = '2014-10-20' THEN `booking_hotelstarttime`
WHEN `booking_hotelend` = '2014-10-20' THEN `booking_endtime`
WHEN `booking_end` = '2014-10-20' THEN `booking_endtime`
END)
LIMIT 0, 100;
However, this is a bit non-sensical, because you are comparing a value to a constant, and then sorting by that value. I suspect you want to prioritize the where clauses and really want something more like this:
ORDER BY (CASE WHEN `booking_start` = '2014-10-20' THEN 1
WHEN `booking_hotelstart` = '2014-10-20' THEN 2
WHEN `booking_hotelend` = '2014-10-20' THEN 3
WHEN `booking_end` = '2014-10-20' THEN 4
END)
Related
I would like to do this query to include the null result in another calculated field.
SELECT ft.fecha_inicio,
ft.fecha_fin,
IF(ft.fecha_fin is NULL, now(), ft.fecha_fin) fin,
TIMEDIFF(fin,ft.fecha_inicio) total,
IF (ISNULL(ft.fecha_fin), 1, 0) as encurso
FROM fabricaciones_tiempos ft
WHERE ft.id_fabricacion = 138;
is this possible?
You cannot directly use a calculated column as part of another column calculation, but you can do it like this:
SELECT
fecha_inicio,
fecha_fin,
TIMEDIFF(fin,fecha_inicio) total,
encurso
FROM (
SELECT ft.fecha_inicio,
ft.fecha_fin,
IF(ft.fecha_fin is NULL, now(), ft.fecha_fin) fin,
IF (ISNULL(ft.fecha_fin), 1, 0) as encurso
FROM fabricaciones_tiempos ft
WHERE ft.id_fabricacion = 138
) as q;
You can't use the alias but you can either include the original formula in place or assign the value to a variable....
SELECT ft.fecha_inicio,
ft.fecha_fin,
IF(ft.fecha_fin is NULL, now(), ft.fecha_fin) fin,
TIMEDIFF(IF(ft.fecha_fin is NULL, now(), ft.fecha_fin),ft.fecha_inicio) total,
IF (ISNULL(ft.fecha_fin), 1, 0) as encurso
FROM fabricaciones_tiempos ft
WHERE ft.id_fabricacion = 138;
or....
SELECT ft.fecha_inicio,
ft.fecha_fin,
#fin:=IF(ft.fecha_fin is NULL, now(), ft.fecha_fin),
TIMEDIFF(#fin,ft.fecha_inicio) total,
IF (ISNULL(ft.fecha_fin), 1, 0) as encurso
FROM fabricaciones_tiempos ft
WHERE ft.id_fabricacion = 138;
I've got the use case to version objects (identified by objectOwnerId and objectId group). I insert rows to ledger table with their respective hashes.
The order of the ledger table is identified by the compound PRIMARY KEY and its timestamp up to microsecond precision + additional 3 byte entropy at the end to prevent collisions (in case multiple rows gets inserted at the same microsecond).
Once data is stored I need efficient way to get the latest hash for multiple objects at once. I've came up with a query (please see end of this post) which is built from sub-selects with JOIN and GROUP BY, but it's pretty complex I think and I am looking for ways to address my problem in a simpler (if possible) way.
Is there any way for improvement?
It would've been simpler if I have PRIMARY KEY which isn't COMPOUND, in which case I could pass the max() value upwards, however that's not the case. I was also thinking if I could merge my TIMESTAMP(6) - 7 bytes with BINARY(3) - 3 bytes and store it as BINARY(10), but wasn't sure if that's easily possible.
Please find the schema, test data and SELECT queries below.
This is my table:
CREATE TABLE `ledger` (
`objectOwnerId` CHAR(10) NOT NULL,
`objectId` VARCHAR(50) NOT NULL,
`objectHash` BINARY(16) NOT NULL,
`timestamp` TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
`timestampAdditionalEntropy` BINARY(3) NOT NULL,
PRIMARY KEY (`timestamp`, `timestampAdditionalEntropy`),
UNIQUE(`objectHash`),
INDEX(`objectId`(10))
);
Let's insert some values:
INSERT INTO ledger (objectOwnerId, objectId, objectHash, timestampAdditionalEntropy) VALUES ('owneraaaaa', 'ida', unhex(substring(sha1(random_bytes(16)), 1, 32)), random_bytes(3));
INSERT INTO ledger (objectOwnerId, objectId, objectHash, timestampAdditionalEntropy) VALUES ('owneraaaaa', 'ida', unhex(substring(sha1(random_bytes(16)), 1, 32)), random_bytes(3));
INSERT INTO ledger (objectOwnerId, objectId, objectHash, timestampAdditionalEntropy) VALUES ('owneraaaab', 'idb', unhex(substring(sha1(random_bytes(16)), 1, 32)), random_bytes(3));
INSERT INTO ledger (objectOwnerId, objectId, objectHash, timestampAdditionalEntropy) VALUES ('owneraaaab', 'idb', unhex(substring(sha1(random_bytes(16)), 1, 32)), random_bytes(3));
INSERT INTO ledger (objectOwnerId, objectId, objectHash, timestampAdditionalEntropy) VALUES ('owneraaaab', 'idb', unhex(substring(sha1(random_bytes(16)), 1, 32)), random_bytes(3));
We've got this dataset:
# objectOwnerId, objectId, objectHash, timestamp, HEX(CAST(timestampAdditionalEntropy AS CHAR(6) CHARACTER SET utf8))
#'owneraaaab', 'idb', 'A8D3B63EFC6C63FD996B8D1931FBF748', '2019-05-29 11:38:12.353521', '725E3D'
#'owneraaaab', 'idb', '9B7395F9EE2F2363BA89C7FBAEDDBB54', '2019-05-29 11:38:12.352524', '8B8162'
#'owneraaaab', 'idb', '80393C5FF4492342D073B5F8B3388EC2', '2019-05-29 11:38:12.351569', 'FEAA02'
#'owneraaaaa', 'ida', '0D84F725ACAC87838C34742CA00BBEF7', '2019-05-29 11:38:12.350648', '41E425'
#'owneraaaaa', 'ida', '9A82C936A25C4648BFB75B692850841B', '2019-05-29 11:38:12.349625', '470685'
returned by this query:
select objectOwnerId, objectId, HEX(CAST(objectHash AS CHAR(32) CHARACTER SET utf8)) as objectHash, timestamp, HEX(CAST(timestampAdditionalEntropy AS CHAR(6) CHARACTER SET utf8))
from ledger
order by timestamp desc, timestampAdditionalEntropy desc;
I need to get this:
# objectOwnerId, objectId, objectHash, timestamp, HEX(CAST(s.timestampAdditionalEntropy AS CHAR(6) CHARACTER SET utf8))
#owneraaaaa, ida, 0D84F725ACAC87838C34742CA00BBEF7, 2019-05-29 11:38:12.350648, 41E425
#owneraaaab, idb, A8D3B63EFC6C63FD996B8D1931FBF748, 2019-05-29 11:38:12.353521, 725E3D
which this query can return:
select s.objectOwnerId, s.objectId, HEX(CAST(objectHash AS CHAR(32) CHARACTER SET utf8)) as objectHash, s.timestamp, HEX(CAST(s.timestampAdditionalEntropy AS CHAR(6) CHARACTER SET utf8)) from (
select s.objectOwnerId, s.objectId, s.timestamp, max(i.timestampAdditionalEntropy) as timestampAdditionalEntropy from (
select objectOwnerId, objectId, max(timestamp) as timestamp
from ledger where ((objectOwnerId = 'owneraaaaa' AND objectId = 'ida') OR (objectOwnerId = 'owneraaaab' AND objectId = 'idb'))
group by objectOwnerId, objectId
) s
JOIN ledger i on i.objectOwnerId = s.objectOwnerId and i.objectId = s.objectId and i.timestamp = s.timestamp
group by objectOwnerId, objectId, timestamp
) s
JOIN ledger i on i.objectOwnerId = s.objectOwnerId and i.objectId = s.objectId and i.timestamp = s.timestamp and i.timestampAdditionalEntropy = s.timestampAdditionalEntropy
How can I express the below statement as a SQL query ?
IF EXISTS (SELECT * FROM expense_history
WHERE user_id = 40
AND DATE_FORMAT(expense_history.created_date , '%Y-%m-%d') = '2018-06-02'
AND camp_id='80')
UPDATE expense_history
SET clicks = clicks + 1,
amount = amount + 1
WHERE user_id = 40
AND DATE_FORMAT(expense_history.created_date, '%Y-%m-%d') = '2018-06-02'
AND camp_id = '80'
ELSE
INSERT INTO expense_history (camp_id, created_date, amount, user_id)
VALUES ('80', '2018-06-02 12:12:12', '1', '40')
END IF;
I just want to do increment clicks and amount if is set by day, else I want to add new row.
This is very tricky in MySQL. You are storing a datetime but you want the date part to be unique.
Starting in MySQL 5.7.?, you can use computed columns for the unique constraint. Here is an example:
create table expense_history (
user_id int,
camp_id int,
amount int default 0,
clicks int default 1,
. . .
created_datetime datetime, -- note I changed the name
created_date date generated always as (date(created_datetime)),
unique (user_id, camp_id, created_datetime)
);
You can then do the work as:
INSERT INTO expense_history (camp_id, created_datetime, amount, user_id)
VALUES (80, '2018-06-02 12:12:12', 1, 40)
ON DUPLICATE KEY UPDATE
amount = COALESCE(amount + 1, 1),
clicks = COALESCE(clicks + 1, 1);
Earlier versions of MySQL don't support generated columns. Nor do they support functions on unique. But you can use a trick on a prefix index on a varchar to do what you want:
create table expense_history (
user_id int,
camp_id int,
amount int default 0,
clicks int default 1,
. . .
created_datetime varchar(19),
unique (created_datetime(10))
);
This has the same effect.
Another alternative is to store the date and the time in separate columns.
I presumed your database is mysql, because of DATE_FORMAT() function(and edited your question as to be).
So, by using such a mechanism below, you can do what you want,
provided that a COMPOSITE PRIMARY KEY for camp_id, amount, user_id columns :
SET #camp_id = 80,
#amount = 1,
#user_id = 40,
#created_date = sysdate();
INSERT INTO expense_history(camp_id,created_date,amount,user_id,clicks)
VALUES(#camp_id,#created_date,#amount,#user_id,ifnull(clicks,1))
ON DUPLICATE KEY UPDATE
amount = #amount + 1,
clicks = ifnull(clicks,0)+1;
SQL Fiddle Demo
I'm trying to update the database, using a script where the ID of a user isn't readily known, so I'm using a subquery to have mysql find the user id (for the posteruserid value). This is the SQL query i'm using:
INSERT INTO `thread` (`title`, `forumid`, `open`, `replycount`,
`postercount`, `postusername`, `postuserid`, `lastposter`,
`dateline`, `visible`, `keywords`)
SELECT 'IN', 2, 1, 0, 1, 'lemons', `userid` FROM `user`
WHERE `username` = 'lemons', 'lemons', 1375768440, 1, 'IN';
I'm getting a syntax error from the above SQL, and I can't figure out what I'm doing wrong.
EDIT because of the mismatched column name, I tried using an alias, which still doesn't work
INSERT INTO `thread` (`title`, `forumid`, `open`, `replycount`,
`postercount`, `postusername`, `postuserid`, `lastposter`,
`dateline`, `visible`, `keywords`)
SELECT 'IN', 2, 1, 0, 1, 'lemons',
`userid` AS `postuserid` FROM `user` WHERE `username` = 'lemons',
'lemons', 1375768440, 1, 'IN';
column mismatch in insert and select query..column should be same where you are going to insert and from where you are fetching data.
You specify to insert values of 11 columns, but in your SELECT statement, you are providing only 7 values. Please provide the value for lastposter,dateline,visible, and keywords.
I have a question relating tables in MySQL. To understand this better I'd rather show you. I have the following table:
CREATE TABLE IF NOT EXISTS `tip_masina` (
`id_tip` int(11) NOT NULL AUTO_INCREMENT,
`marca` varchar(40) NOT NULL,
`pret` int(11) NOT NULL,
PRIMARY KEY (`id_tip`),
UNIQUE KEY `marca` (`marca`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=16 ;
INSERT INTO `tip_masina` (`id_tip`, `marca`, `pret`) VALUES
(1, 'Chevrolet Impala', 8000),
(2, 'Chevrolet Camaro', 10000),
(3, 'Chevrolet Tahoe', 13000),
(4, 'Chevrolet Suburban', 12500),
(5, 'Chevrolet Cobalt', 4000),
(6, 'Dodge Charger', 14000),
(7, 'Dodge Avenger', 9000),
(8, 'Dodge Challenger', 6500),
(9, 'Dodge Dart', 3500),
(10, 'Dodge Durango', 3000),
(11, 'Ford Mustang', 7500),
(12, 'Ford Crown Victoria', 5000),
(13, 'Ford Focus', 4300),
(14, 'Ford Fiesta', 3700),
(15, 'Ford Escort', 1000);
What I want out of this table is to display the vehicle type and the number of vehicles, like:
marca | no_of_vehicles
Chevrolet 5
Dodge 5
Ford 5
Is there any way to do this without splitting the column marca in two columns?
Here is an easy way, using substring_index():
select substring_index(marca, ' ', 1) as marca, count(*)
from tip_masina
group by substring_index(marca, ' ', 1);
It might be better to split 'marca' into two columns so that it would be easier to find what you want. You won't need any special functions then (as e.g. substring_index).
EDIT:
You can use following code:
EDIT2:
Now it works (tested on mysql workbench with your queries creating table):
START TRANSACTION;
ALTER TABLE tip_masina ADD model VARCHAR(60) AFTER marca;
ALTER TABLE tip_masina CHANGE marca company VARCHAR(60);
UPDATE tip_masina SET model = SUBSTRING_INDEX(company, ' ', -1);
ALTER TABLE tip_masina DROP INDEX marca;
UPDATE tip_masina SET company = SUBSTRING_INDEX(company, ' ', 1);
SELECT * FROM tip_masina;