Hypothetical question for the community :
Given any 2 books in a library (book 1,book 2), how many customers have had both checked out at the same time within the year?
Table
CREATE TABLE `check0` (
`lib_card_num` int NOT NULL,
`first_name` varchar(45) NOT NULL,
`last_name` varchar(45) NOT NULL,
`checkout_timestamp_utc` timestamp(6) NOT NULL,
`due_date` date NOT NULL,
`type` varchar(10) DEFAULT NULL,
`name` varchar(45) DEFAULT NULL,
`unique_id` int NOT NULL,
PRIMARY KEY (`unique_id`),
KEY `parent_index1` (`lib_card_num`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
;
Data
INSERT INTO testlibrary.check0
(lib_card_num,FIRST_NAME,LAST_NAME,CHECKOUT_TIMESTAMP_UTC,DUE_DATE,TYPE,NAME,UNIQUE_ID)
VALUES
(1,'ROB','BLOW',DATE_ADD(current_timestamp(), INTERVAL -30 day),DATE_ADD(current_date(),INTERVAL -5 DAY),'PHYSICAL','SHEBA',100),
(1,'ROB','BLOW',DATE_ADD(current_timestamp(), INTERVAL -30 day),DATE_ADD(current_date(),INTERVAL -5 DAY),'ELECTRONIC','THUNDERPOINT',101),
(2,'JOHN','DOE',DATE_ADD(current_timestamp(), INTERVAL -15 day),DATE_ADD(current_date(),INTERVAL -1 DAY),'ELECTRONIC','THUNDERPOINT',102),
(2,'JOHN','DOE',DATE_ADD(current_timestamp(), INTERVAL -15 day),DATE_ADD(current_date(),INTERVAL -1 DAY),'PHYSICAL','SHEBA',103),
(3,'JANE','DOE',DATE_ADD(current_timestamp(), INTERVAL -45 day),DATE_ADD(current_date(),INTERVAL -20 DAY),'PHYSICAL','SHEBA',104),
(3,'JANE','DOE',DATE_ADD(current_timestamp(), INTERVAL -45 day),DATE_ADD(current_date(),INTERVAL -20 DAY),'ELECTRONIC','THUNDERPOINT',105)
Maybe try this
select count(lib_card_num) as result
from
(select distinct check0.lib_card_num from sys.check0
where check0.checkout_timestamp_utc in
(SELECT checkout_timestamp_utc
FROM
(SELECT check0.checkout_timestamp_utc, COUNT(check0.checkout_timestamp_utc) count
FROM sys.check0
GROUP BY check0.checkout_timestamp_utc) sub1
WHERE sub1.count > 1)) sub2;
Given any 2 books in a library (book 1,book 2), how many customers have had both checked out at the same time within the year?
This doesn't sound very theoretical. But you can approach this using aggregation. However, your description doesn't have a column called customer or book_title, so you'll need to adapt for your data model. This is a theoretical question after all:
To get the customers with both books:
select customer
from check0 c
where book_title in ('book 1', 'book 2')
group by customer
having count(distinct book_title) = 2;
You can then count these with an additional subquery:
select count(*)
from (select customer
from check0 c
where book_title in ('book 1', 'book 2')
group by customer
having count(distinct book_title) = 2
) c;
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 want to sum all the values in a specific date in mysql but idk what is the right syntax
CREATE TABLE `trans` (
`id` int(12) NOT NULL,
`date_sold` datetime NOT NULL,
`total` varchar(255) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
ALTER TABLE `trans`
ADD PRIMARY KEY (`id`);
ALTER TABLE `trans`
MODIFY `id` int(12) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=8;
id
date_sold
total
1
2021-02-23
12
2
2021-02-23
6
3
2021-02-24
32
4
2021-02-24
10
now i want to sum all the values in that specific date
ex:
id
date
total
1
2021-02-23
18
2
2021-02-24
42
is that possible?
Alternative Use of ROW_NUMBER() function. Because ROW_NUMBER() isn't supported in below v5.8. First calculate date wise total and then apply id incrementally.
-- MySQL(5.6)
SELECT (#row_number:= #row_number + 1) id
, t.date_sold, t.total
FROM (SELECT date_sold
, SUM(total) total
FROM trans
GROUP BY date_sold ) t, (SELECT #row_number := 0) x
ORDER BY t.date_sold
Please check from URL https://dbfiddle.uk/?rdbms=mysql_5.6&fiddle=5cc2305b465ac2454be5bdb1a9e8af4a
I'm trying to find a row immediately before and after a given row, with a order by clause. The use case is "previous entry" and "next entry" links in a vaguely blog-like system. The engine is MySQL 5.6. The table schema is
CREATE TABLE `weekly_notes` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`year` int(4) DEFAULT NULL,
`week_number` int(11) DEFAULT NULL,
`header_text` text NOT NULL,
`image_filename` varchar(128) DEFAULT NULL,
`boundry_image_filename` varchar(128) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8;
and the query is ordered by year desc, week_number desc. The criteria for selecting a row is year and week_number.
Sample Data
insert into weekly_notes values
(101,2018,53,'Week 53 from year 2018',NULL,NULL),
(102,2019,50,'Week 50 from year 2019', NULL, NULL),
(103,2019,51,'Week 51 from year 2019', NULL, NULL),
(104,2019,52,'Week 52 from year 2019', NULL, NULL),
(105,2020,1,'Week 1 from year 2020', NULL, NULL),
(106,2019,53,'Week 53 from year 2019', NULL, NULL),
(107,2020,2,'Week 2 from year 2020', NULL, NULL),
(108,2020,3,'Week 3 from year 2020', NULL, NULL),
(109,2020,4,'Week 4 from year 2020', NULL, NULL);
The select criteria are year an week, so I would like to be able to select the week "before" 2020-01 and get the row for 2019-53 or the week before 2020-03 and get the row for 2020-02
You can use lag() -- on however you are defining the ordering. For instance, if you wanted the row after a certain header_text:
select wn.*
from (select wn.*,
lag(header_text) over (order by year, week) as prev_header_text
from weekly_notes wn
) wn
where prev_header_text = <what you are looking for>
This assumes that "after" is chronological. I suppose "after" with a descending sort could actually mean the row before, in which case you would use lead() instead of lag().
For before a particular week/year combo, you can use:
select wn.*
from (select wn.*,
lag(week) over (order by year, week) as prev_week,
lag(year) over (order by year, week) as prev_year
from weekly_notes wn
) wn
where prev_week = #week and prev_year = #year
This is the definition of the "exchange" table:
CREATE TABLE `exchange` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`rank` int(11) NOT NULL,
`name` varchar(255) NOT NULL,
`volume` varchar(255) NOT NULL,
`timestamp` datetime NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=75032 DEFAULT CHARSET=utf8;
About 209 records will store every 5 minutes.
How can I get this data structure?
rank, name, [volume,...](last 144 value), timestamp
I use this query:
SELECT `volume`
FROM `exchange`
WHERE `exchange`.`name` = 'binance'
ORDER BY `timestamp` DESC
LIMIT 144
Is there better way to get the data once? Thanks.
Frankly, your method might be the best method, particularly if you have an index on (name, timestamp).
You can try:
select e.volume
from exchange e
where e.timestamp >= (select e2.timestamp
from exchange e2
where e2.name = e.name
limit 1 offset 143
);
You can then aggregate the values as:
select e.name, sum(e.volume)
from exchange e
where e.timestamp >= (select e2.timestamp
from exchange e2
where e2.name = e.name
limit 1 offset 143
)
group by e.name;
Note: In MySQL 8+, this is much simpler using row_number():
select name, sum(volume)
from (select e.*,
row_number() over (partition by name order by timestamp desc) as seqnum
from exchange e
) e
where seqnum <= 144
group by name;
Currently I am working on a project, which has to do with Formula 1.
That's my structure of the table for results.
CREATE TABLE IF NOT EXISTS `races_results` (
`resultid` int(11) NOT NULL,
`seasonyear` int(4) NOT NULL,
`trackid` tinyint(2) NOT NULL,
`raceid` int(2) NOT NULL,
`session` tinyint(1) NOT NULL,
`q` int(11) NOT NULL,
`place` tinyint(2) NOT NULL,
`driverid` int(2) NOT NULL,
`teamid` int(2) NOT NULL,
`time` int(11) NOT NULL,
`laps` int(2) NOT NULL,
`status` varchar(3) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
My big problem is that I don't get the result in output as I want.
SELECT place, driverid, teamid, if(q=1, time, '') as time1, if(q=2, time, '') as time2, if(q=3, time, '') as time3
FROM `races_results`
WHERE `seasonyear` = 2015 AND `raceid` = 3 AND `session` = 2 AND `q` IN (1,2,3)
GROUP BY driverid
ORDER BY CASE WHEN q = 3 THEN place >= 1 AND place <= 10 END ASC, CASE WHEN q = 2 THEN place >= 11 AND place <= 16 END ASC, CASE WHEN q = 1 THEN place >= 17 AND place <= 22 END ASC
My target is that I want that the all times of a driver will show side by side and after this should be ordered by the participants of the sections.
After this I should have an output like this http://www.formula1.com/content/fom-website/en/championship/results/2015-race-results/2015-japan-results/qualifying.html
From your question I understand that the table races_results has a line for each result, so the times of the different qualifications are on different lines. To get these on one line you can do a join of the same table:
SELECT place, driverid, teamid, r1.time as time1, r2.time as time2, r3.time as time3
FROM races_results r1 LEFT JOIN races_results r2 on (r1.driverid=r2.driverid and r1.raceid=r2.raceid)
LEFT JOIN races_results r3 on (r1.driverid=r3.driverid and r1.raceid=r3.raceid)
WHERE r1.q=1 AND r2.q=2 AND r3.q=3 AND
`seasonyear` = 2015 AND `raceid` = 3 AND `session` = 2
GROUP BY driverid
ORDER BY place;
I assume:
that there is always a result for q=1;
the driverid and raceid are unique for a race on a specific year for a driver;
you want to order by place.