Syntax error near ( - mysql

I am trying to query something and I am not so good with Mysql, so I was wondering if someone can tell me what is the issue here. Here is my table:
create table #transfers (
sender varchar not null,
recipient varchar not null,
date date not null,
amount integer not null
);
INSERT INTO #transfers(sender,recipient,date,amount) VALUES ('Smith','Williams','2000-01-01',200);
INSERT INTO #transfers(sender,recipient,date,amount) VALUES ('Smith','Taylor','2002-09-27',1024);
INSERT INTO #transfers(sender,recipient,date,amount) VALUES ('Smith','Johnson','2005-06-26',512);
INSERT INTO #transfers(sender,recipient,date,amount) VALUES ('Williams','Johnson','2010-12-17',100);
INSERT INTO #transfers(sender,recipient,date,amount) VALUES ('Williams','Johnson','2004-03-22',10);
INSERT INTO #transfers(sender,recipient,date,amount) VALUES ('Brown','Johnson','2013-03-20',500);
INSERT INTO #transfers(sender,recipient,date,amount) VALUES ('Johnson','Williams','2007-06-02',400);
INSERT INTO #transfers(sender,recipient,date,amount) VALUES ('Johnson','Williams','2005-06-26',400);
INSERT INTO #transfers(sender,recipient,date,amount) VALUES ('Johnson','Williams','2005-06-26',200);
This is the query:
WITH cte AS
(
SELECT *, rn = ROW_NUMBER() OVER (PARTITION BY recipient ORDER BY amount DESC)
FROM #transfers
)
SELECT recipient
FROM cte
WHERE rn <= 3
GROUP BY recipient
HAVING SUM(amount) >= 1024
ORDER BY recipient
However I get this error:
near "(": syntax error

CTEs and ROW_NUMBER are not available in MySQL.
Try with Subquery:
SELECT recipient
FROM
(
SELECT t.*, #rownum := #rownum + 1 AS rank
FROM #transfers t, (SELECT #rownum := 0) r
)X
WHERE rank <= 3
GROUP BY recipient
HAVING SUM(amount) >= 1024
ORDER BY recipient
Fiddle Demo

use this create table query
create table transfers (
id INT NOT NULL AUTO_INCREMENT,
sender VARCHAR(100) NOT NULL,
recipient VARCHAR(100) NOT NULL,
date DATE,
amount VARCHAR(100) NOT NULL,
PRIMARY KEY ( id )
);

Related

Replace null values with previous values in timesent

I am trying to replace null values with previous available record. i try to search answer for this query on stakeoverflow however, those answers are quite confusing hence looking for simple answer alone with explaination.
tried to get the previous value of the null value but it shows 0 records using this query :
CREATE TABLE messages (
channelid INTEGER,
messageid INTEGER,
timesent DATETIME
);
INSERT INTO messages (channelid, messageid, timesent)
VALUES (10, 2, '2022-07-04 04:04');
INSERT INTO messages (channelid, messageid, timesent)
VALUES (10, 5, '2022-07-04 08:04');
INSERT INTO messages (channelid, messageid, timesent)
VALUES (10, 3, NULL);
INSERT INTO messages (channelid, messageid, timesent)
VALUES (10, 7, '2022-07-04 08:04');
`SELECT timesent
FROM messages
WHERE timesent < messages.timesent and not null `
SQL fiddle
Supposing that the messageid column specifies the order of messages by which we can define what the previous value is, you can use a subquery as the following:
select channelid, messageid,
(
select timesent from messages t2
where t2.channelid = t1.channelid and
t2.messageid <= t1.messageid and
t2.timesent is not null
order by t2.messageid desc limit 1
) timesent
from messages t1
order by messageid
Another approch, you can use the conditional max window function to define groups that connect the null values with the last not null value as the following:
select channelid, messageid,
coalesce(timesent, max(timesent) over (partition by channelid, grp)) as timesent
from
(
select *,
max(case when timesent is not null then messageid end) over
(partition by channelid order by messageid) as grp
from messages
) t
order by messageid
And if the timesent value will not be decreased with the increasing of the messageid value, then you can use the running max window function as the following:
select channelid, messageid, timesent_not_null as timesent
from
(
select *,
max(timesent) over (partition by channelid order by messageid) timesent_not_null
from messages
) t
-- where some condition (if needed)
order by messageid
See demo

MySQL Selecting wrong column value in Group By query with alias in where clause

I know this question was already asked in a similar way, but I could not found any with an alias in the where clause.
I have a table structure like this:
CREATE TABLE Orders
( ID int NOT NULL Primary Key
, OrderNr VARCHAR(6) NOT NULL
, Date DATE NOT NULL
, Time CHAR(6) NOT NULL
, GeoCode CHAR(6) NULL) ;
My insert looks like this:
INSERT INTO orders (ID, OrderNr, Date, Time, GeoCode) VALUES (1, '123456', '2022-02-
15', '111110', '4022')
, (2, '123457', '2022-02-15', '121210', '4022')
, (3, '123455', '2021-04-15', '171515', '4020')
, (4, '123455', '2021-04-16', '150302', '4022')
, (5, '123466', '2022-03-03', '191810', '4020')
, (6, '123466', '2022-03-04', '121410', '4022')
Now I´m trying to get the latest Date and Time values for all OrderNr like this:
SELECT ID, OrderNr, MAX(cast(concat(Date, ' ', cast(Time as Time)) as datetime)) as
DateAndTime, GeoCode
FROM Orders o1
GROUP BY OrderNr
The Results shows the right latest date and time but the GeoCode is wrong. E.g for the
OrderNr 123455 it is 4020 but should be 4022.
I know that similar question were already asked but I cant use the alias in the where clause. Can somebody explain to me what I´m doing wrong?
Thank you very much in advance.
If your mysql version support ROW_NUMBER window function you can try this
SELECT *
FROM (
SELECT ID,
OrderNr,
cast(concat(Date, ' ', cast(Time as Time)) as datetime) DateAndTime,
GeoCode,
ROW_NUMBER() OVER(PARTITION BY OrderNr ORDER BY cast(concat(Date, ' ', cast(Time as Time)) as datetime) DESC) rn
FROM Orders o1
) t1
WHERE rn = 1
or use subquery with EXISTS
SELECT *
FROM Orders o1
WHERE EXISTS (
SELECT 1
FROM Orders oo
WHERE oo.OrderNr = o1.OrderNr
HAVING MAX(oo.Date) = o1.Date
)
sqlfiddle

Operand Should Contain 1 Column(s), Trying to generate volunteer data

I can't seem to troubleshoot my problem.
My stored procedure:
CREATE DEFINER=`myschoolusername`#`%` PROCEDURE `generate_volunteers`(in nfolks int)
BEGIN
set #i=0;
while #i < nfolks do
insert into Volunteer(firstname, lastname, dateofbirth)
values (((floor(1+(rand()*(4-1))), "Fred", "Wang", "Fatimah", "Marcella")),
((floor(1+(rand()*(3-1))), "Kaser", "Fang", "Kumar")),
DATE_ADD('1965-01-01', INTERVAL rand()*200000 DAY));
set #i = #i+1;
end while;
END
Additionally, here is my volunteer table in my MYSQL script:
drop table if exists Volunteer;
create Table Volunteer(
member_num int not null auto_increment primary key,
firstname varchar(20) not null,
lastname varchar(20) not null,
dateofbirth date not null
);
I am trying to insert 500 lines into this table, however error 1305 is coming up.
Any help is heavily appreciated, I am quite unsure of where to go from this point.
This logic doesn't do anything:
(floor(1+(rand()*(4-1))), "Fred", "Wang", "Fatimah", "Marcella"))
Although not the most efficient, this should be fine for 500 rows:
insert into Volunteer(firstname, lastname, dateofbirth)
select f.firstname, l.lastname,
DATE_ADD('1965-01-01', INTERVAL rand()*200000 DAY)
from (select 'Fred' as firstname union all
select 'Wang' union all
select 'Fatimah' union all
select 'Marcella'
) f cross join
(select 'Kaser' as lastname union all
select 'Fang' union all
select 'Kumar'
) l
order by rand()
limit 1;
I think you are actually trying to write:
insert into Volunteer(firstname, lastname, dateofbirth)
select elt(floor(rand() * 4) + 1,
'Fred', 'Wang', 'Fatimah', 'Marcella'
) as firstname,
elt(floor(rand() * 3) + 1,
'Kaser', 'Fang', 'Kumar'
) as lastname,
DATE_ADD('1965-01-01', INTERVAL rand()*200000 DAY);

How to sort by timestamp streaks SQL

Say I have the following tables (simplified version of what I'm working with):
CREATE TABLE posts (
id INTEGER,
title VARCHAR(255),
text TEXT,
author_id INTEGER,
created_at TIMESTAMP
);
CREATE TABLE authors (
id INTEGER,
name VARCHAR(255),
email VARCHAR(255)
);
What I want to do is retrieve only the authors but order them by number of one-week streaks. That is, number of consecutive weeks an author published a post. The time a post has been made is stored in the posts created_at column
What I'm having the most difficulty with is understanding how to calculate the difference in time between posts across rows. I’m using MySQL
Without window functions it's a bit hard to do in MySql 5.7
But here's an experiment test snippet that uses variables :
Sample data:
DROP TABLE IF EXISTS `posts`;
DROP TABLE IF EXISTS `authors`;
CREATE TABLE `authors` (
id INTEGER PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(255),
email VARCHAR(255)
);
CREATE TABLE `posts` (
id INTEGER PRIMARY KEY AUTO_INCREMENT,
title VARCHAR(255),
`text` TEXT,
author_id INTEGER,
created_at TIMESTAMP,
CONSTRAINT fk_posts_author_id FOREIGN KEY (author_id) REFERENCES `authors`(id)
);
insert into `authors` (name, email) values
('john doe', 'john.doe#home.net'),
('jane sheppard', 'jane.sheppard#home.net');
insert into `posts` (author_id, created_at, title, `text`) values
(1, '2019-02-07', 'When', 'bla'),
(1, '2019-02-09', 'I', 'bla2'),
(1, '2019-02-14', 'Start', 'bla3'),
(1, '2019-02-19', 'looking', 'bla4'),
(1, '2019-03-10', '...', 'bla5'),
(2, '2019-02-01', 'I', 'blah1'),
(2, '2019-02-05', 'frighten', 'blah2'),
(2, '2019-02-19', 'even', 'blah3'),
(2, '2019-03-20', 'myself', 'blah4');
Query:
SELECT q3.ConcurrentWeeks, q3.StartWeekDate, a.*
FROM
(
SELECT COUNT(*) as ConcurrentWeeks, MIN(WkDt) as StartWeekDate, author_id
FROM
(
SELECT q1.WkDt, q1.Total
, case
when #author = author_id and #yr = yr and #wk = wk-1 then #rnk
else #rnk := #rnk + 1
end as rnk
, #author := author_id as author_id
, #yr := yr as yr
, #wk := wk as wk
FROM
(
SELECT
author_id, YEAR(created_at) as yr, WEEK(created_at) as wk
, COUNT(*) AS Total
, COALESCE(MIN(STR_TO_DATE(concat(YEAR(created_at),' monday ',WEEK(created_at)),'%X %W %V')), MIN(CAST(created_at AS DATE))) AS WkDt
FROM `posts` p
GROUP BY author_id, YEAR(created_at), WEEK(created_at)
ORDER BY author_id, yr, wk
) q1
CROSS JOIN (select #author := null, #yr := null, #wk := null, #rnk := 0) init
) q2
GROUP BY author_id, rnk
HAVING ConcurrentWeeks > 1
) q3
LEFT JOIN `authors` a ON a.id = q3.author_id
ORDER BY ConcurrentWeeks DESC, StartWeekDate ASC
Result:
ConcurrentWeeks StartWeekDate id name email
--------------- ------------- -- ------------- ----------------------
3 2019-02-04 1 john doe john.doe#home.net
2 2019-01-28 2 jane sheppard jane.sheppard#home.net

need select from two fields, unique in first based on highest of second

I have a table with three fields, an ID, a Date(string), and an INT. like this.
+---------------------------
+BH|2012-09-01|56789
+BH|2011-09-01|56765
+BH|2010-08-01|67866
+CH|2012-09-01|58789
+CH|2011-09-01|56795
+CH|2010-08-01|67866
+DH|2012-09-01|52789
+DH|2011-09-01|56665
+DH|2010-08-01|67866
I need to essentially for each ID, i need to return only the row with the highest Date string. From this example, my results would need to be.
+---------------------------
+BH|2012-09-01|56789
+CH|2012-09-01|58789
+DH|2012-09-01|52789
SELECT t.id, t.date_column, t.int_column
FROM YourTable t
INNER JOIN (SELECT id, MAX(date_column) AS MaxDate
FROM YourTable
GROUP BY id) q
ON t.id = q.id
AND t.date_column = q.MaxDate
SELECT id, date, int
FROM ( SELECT id, date, int
FROM table_name
ORDER BY date DESC) AS h
GROUP BY id
Replace table_name and columns to the right ones.
Assuming the following structure:
CREATE TABLE `stackoverflow`.`table_10357817` (
`Id` int(11) NOT NULL AUTO_INCREMENT,
`Date` datetime NOT NULL,
`Number` int(11) NOT NULL,
`Code` char(2) NOT NULL,
PRIMARY KEY (`Id`) USING BTREE
) ENGINE=MyISAM AUTO_INCREMENT=11 DEFAULT CHARSET=latin1
The following query will wield the expected results:
SELECT Code, Date, Number
FROM table_10357817
GROUP BY Code
HAVING Date = MAX(Date)
The GROUP BY forces a single result per Code (you called it id) and the HAVING clauses returns only the data where it matches the max date per code/id.
Update
Used the following data script:
INSERT INTO table_10357817
(Code, Date, Number)
VALUES
('BH', '2012-09-01', 56789),
('BH', '2011-09-01', 56765),
('BH', '2010-08-01', 67866),
('CH', '2012-09-01', 58789),
('CH', '2011-09-01', 56795),
('CH', '2010-08-01', 67866),
('DH', '2012-09-01', 52789),
('DH', '2011-09-01', 56665),
('DH', '2010-08-01', 67866)