Is Offset should specify at the end of Sql query? - mysql

SELECT * CUSTOMERS LIMIT 5 OFFSET 0.
Assume CUSTOMERS is table of details. The above query works fine but if i specify offset other than end of query i get error.
Created a table with following details.
Table name is sms_view
Query:
SELECT SMS FROM sms_view WHERE read=2 LIMIT 5 OFFSET 0;
Result is
The above result is expected and it is based on read value. So, the table is created based on read value, offset and limit applied on the created table. so the result is shown above.
But My requirement is, offset and Limit should apply on entire table and read value should apply on created table.
Expected result is:
I need a query on expected result.

Yes, it should be at the end. See https://dev.mysql.com/doc/refman/5.7/en/select.html
SELECT * FROM CUSTOMERS
ORDER BY somecolumn -- important to get consistent results
LIMIT 5 OFFSET 0
Another way to do the same thing is:
SELECT * FROM CUSTOMERS
ORDER BY somecolumn
LIMIT 0, 5
or in this case (as the offset is 0):
SELECT * FROM CUSTOMERS
ORDER BY somecolumn
LIMIT 5

MariaDB [sandbox]> Drop table if exists sms_view;
Query OK, 0 rows affected (0.10 sec)
MariaDB [sandbox]> create table sms_view(SMS int,db_id int, `read` int);
Query OK, 0 rows affected (0.28 sec)
MariaDB [sandbox]> insert into sms_view values
-> (1, 2, 3) ,
-> (2, 2, 3),
-> (3, 2, 2) ,
-> (4, 2, 2) ,
-> (5, 2, 2) ,
-> (6, 2, 2) ,
-> (7, 2, 2) ,
-> (8, 2, 2) ,
-> (9, 2, 2) ,
-> (10, 2, 2);
Query OK, 10 rows affected (0.04 sec)
Records: 10 Duplicates: 0 Warnings: 0
MariaDB [sandbox]>
MariaDB [sandbox]> select sms from
-> (
-> SELECT * FROM sms_view LIMIT 5 OFFSET 0
-> ) s
-> WHERE `read` = 2;
+------+
| sms |
+------+
| 3 |
| 4 |
| 5 |
+------+
3 rows in set (0.00 sec)

Related

SQL Insert many rows - one value changes - number of rows is dynamic

I need to do do an insert where 2 values will be constant and the third will change. So, something like the following:
INSERT INTO
`example_table`(column_a, column_b,column_c)
SELECT 1, [3,4], 409187710
from `example_table`
Desired Result:
column_a
column_b
column_c
1
3
409187710
1
4
409187710
Just to be clear the number of values I need to insert into column_b will vary - sometimes I will need to insert 2 values, sometimes I may need to insert 10 values, but columns a and c will always have the same values. How do I perform such an insert?
My question differs from this question in that a sql case statement will not suffice. This is a different kind of problem.
MySQL 8.0 has a new kind of statement: VALUES.
mysql> create table example_table (column_a int, column_b int, column_c int);
Query OK, 0 rows affected (0.01 sec)
mysql> insert into example_table
-> select 1, column_0, 409187710 from (values row(3), row(4)) as t;
Query OK, 2 rows affected (0.00 sec)
Records: 2 Duplicates: 0 Warnings: 0
mysql> select * from example_table;
+----------+----------+-----------+
| column_a | column_b | column_c |
+----------+----------+-----------+
| 1 | 3 | 409187710 |
| 1 | 4 | 409187710 |
+----------+----------+-----------+
If you use a version of MySQL that doesn't support the VALUES statement, you can use this syntax:
mysql> insert into example_table
-> select 1, b, 409187710 from (select 3 as b union select 4) as t;

Improve ORDER BY RAND() in large table [duplicate]

This question already has answers here:
MySQL select 10 random rows from 600K rows fast
(28 answers)
quick selection of a random row from a large table in mysql
(24 answers)
Closed last year.
I have a very large table with about 6.6 million records and I want to select a random sample of 100,000 records
SELECT column FROM table
ORDER BY RAND()
LIMIT 100000
Is EXTREMELY SLOW on each record.
I have not found a solution that works with MySQL/MariaDB to extract a random sample of 100,000 records.
Please advise.
Thank you.
You may try to decrease the amount of rows to be sorted.
Example:
Create source data
mysql> create table test (id int auto_increment primary key, val int);
Query OK, 0 rows affected (0.05 sec)
mysql> set ##cte_max_recursion_depth := 10000000;
Query OK, 0 rows affected (0.00 sec)
mysql> insert into test (val) with recursive cte as ( select 1 num union all select num+1 from cte where num < 6600000 )select rand() * 1000000000 from cte;
Query OK, 6600000 rows affected (1 min 48.62 sec)
Records: 6600000 Duplicates: 0 Warnings: 0
mysql> create table tmp (val int);
Query OK, 0 rows affected (0.05 sec)
Insert without sorting
mysql> insert into tmp select val from test limit 100000;
Query OK, 100000 rows affected (1.93 sec)
Records: 100000 Duplicates: 0 Warnings: 0
Insert with random sorting
mysql> insert into tmp select val from test order by rand() limit 100000;
Query OK, 100000 rows affected (26.31 sec)
Records: 100000 Duplicates: 0 Warnings: 0
Insert with random selection (1.1 is overage coefficient)
mysql> insert into tmp select val from test where rand() < 1.1 * 100000 / 6600000 limit 100000;
Query OK, 100000 rows affected (15.89 sec)
Records: 100000 Duplicates: 0 Warnings: 0
Insert with random selection (1.1 is overage coefficient) and random sorting
mysql> insert into tmp select val from test where rand() < 1.1 * 100000 / 6600000 order by rand() limit 100000;
Query OK, 100000 rows affected (19.26 sec)
Records: 100000 Duplicates: 0 Warnings: 0
Overage coefficient may be adjusted. If you decrease it then you'll improve the query (slightly) but the probability that the amount of output rows will be less than needed 100k rows will increase.

Modify a SQL table to condense similar rows while summing up a column

Here is a question that is the general gist of what I am trying to do:
Sum values from multiple rows into one row
However, to my knowledge, I am seeking further functionality, which would permanently modify the table in question to look like the result of the SELECT statement that is being suggested in that other thread.
So the table:
Sales
--------------------------------------
account product qty amount
--------------------------------------
01010 bottle 10 200
01010 bottle 20 100
01010 bottle 5 10
11111 can 50 200
11111 can 25 150
...would be permanently modified to look like this
Sales
--------------------------------------
account product qty amount
--------------------------------------
01010 bottle 35 310
11111 can 75 350
As is answered in the link, using a SELECT with SUM and GROUP BY can show me what the table needs to look like, but how to I actually apply those changes to the sales table?
edit: This query will be run every time a new batch of sales is added into the system. It's intended to clean up the sales table after new records have been added.
Alternative approach
New records in sales are inserted in from a different table using something like this:
"INSERT INTO sales
SELECT account, product, qty, amount
FROM new_sales;"
If there is a way to take care of the summation during that previous INSERT, instead of adding duplicate rows in the first place, that would also be acceptable. Keep in mind, this solution would still need to work for new records that don't have existing duplicate rows in sales.
EDIT: for posterity
General response seems to be that my initial approach is not possible-- short of creating a temp_sales table with a CREATE and SELECT, then purging sales completely, and then copying the contents of temp_sales into the cleared sales table, and truncating temp_sales for future use.
The accepted solution uses the "Alternative approach" that I had also alluded to.
Assuming new_sales is truncated after sales has been updated and then starts to refill you could use insert..on duplicate key..update for example
MariaDB [sandbox]> drop table if exists t,t1;
Query OK, 0 rows affected (0.20 sec)
MariaDB [sandbox]>
MariaDB [sandbox]> create table t
-> (account varchar(5), product varchar(20), qty int default 0, amount int default 0);
Query OK, 0 rows affected (0.16 sec)
MariaDB [sandbox]> create table t1
-> (account varchar(5), product varchar(20), qty int default 0, amount int default 0);
Query OK, 0 rows affected (0.24 sec)
MariaDB [sandbox]>
MariaDB [sandbox]> alter table t
-> add unique key k1(account,product);
Query OK, 0 rows affected (0.15 sec)
Records: 0 Duplicates: 0 Warnings: 0
MariaDB [sandbox]>
MariaDB [sandbox]> truncate table t1;
Query OK, 0 rows affected (0.23 sec)
MariaDB [sandbox]> insert into t1 values
-> ('01010' , 'bottle' , 10 , 200),
-> ('01010' , 'bottle' , 20 , 100),
-> ('01010' , 'bottle' , 5 , 10),
-> ('11111' , 'can' , 50 , 200),
-> ('11111' , 'can' , 25 , 150);
Query OK, 5 rows affected (0.02 sec)
Records: 5 Duplicates: 0 Warnings: 0
MariaDB [sandbox]>
MariaDB [sandbox]> truncate table t;
Query OK, 0 rows affected (0.28 sec)
MariaDB [sandbox]> insert into t
-> select account,product,t1qty,t1amount
-> from
-> (
-> select t1.account,t1.product,sum(t1.qty) t1qty,sum(t1.amount) t1amount from t1 group by t1.account,t1.product
-> ) s
-> on duplicate key
-> update qty = t.qty + t1qty, amount = t.amount + t1amount;
Query OK, 2 rows affected (0.02 sec)
Records: 2 Duplicates: 0 Warnings: 0
MariaDB [sandbox]>
MariaDB [sandbox]> truncate table t1;
Query OK, 0 rows affected (0.32 sec)
MariaDB [sandbox]> insert into t1 values
-> ('01010' , 'bottle' , 10 , 200),
-> ('01011' , 'bottle' , 20 , 100),
-> ('01011' , 'bottle' , 5 , 10),
-> ('11111' , 'can' , 50 , 200),
-> ('11111' , 'can' , 25 , 150);
Query OK, 5 rows affected (0.02 sec)
Records: 5 Duplicates: 0 Warnings: 0
MariaDB [sandbox]>
MariaDB [sandbox]> insert into t
-> select account,product,t1qty,t1amount
-> from
-> (
-> select t1.account,t1.product,sum(t1.qty) t1qty,sum(t1.amount) t1amount from t1 group by t1.account,t1.product
-> ) s
-> on duplicate key
-> update qty = t.qty + t1qty, amount = t.amount + t1amount;
Query OK, 5 rows affected (0.02 sec)
Records: 3 Duplicates: 2 Warnings: 0
MariaDB [sandbox]>
MariaDB [sandbox]>
MariaDB [sandbox]> select * from t;
+---------+---------+------+--------+
| account | product | qty | amount |
+---------+---------+------+--------+
| 01010 | bottle | 45 | 510 |
| 11111 | can | 150 | 700 |
| 01011 | bottle | 25 | 110 |
+---------+---------+------+--------+
3 rows in set (0.00 sec)
MariaDB [sandbox]>
You can create a table from a select statement.
So you could do something like:
create table sales_sum as
select
account,
product,
sum(qty),
sum(amount)
from
sales
group by
account,
product
That creates a table with the right structure, and it'll insert the records that you want to have. Of course you can adapt the query or the table name.
This query does what a ETL tool can do but every you need to run the entire script :
----------Old Table
CREATE TABLE yourtable (
[state] varchar(2),
[month] varchar(7),
[ID] int,
[sales] int
)
;
INSERT INTO yourtable ([state], [month], [ID], [sales])
VALUES ('FL', 'June', 0001, '12000'),
('FL', 'June', 0001, '6000'),
('FL', 'June', 0001, '3000'),
('FL', 'July', 0001, '6000'),
('FL', 'July', 0001, '4000'),
('TX', 'January', 0050, '1000'),
('MI', 'April', 0032, '5000'),
('MI', 'April', 0032, '8000'),
('CA', 'April', 0032, '2000');
SELECT
state,
month,
id,
SUM(sales) Total
FROM yourtable
GROUP BY state,
month,
id;
-----Creating new table from old table
CREATE TABLE yourtable1 (
[state] varchar(2),
[month] varchar(7),
[ID] int,
[sales] int
)
;
----Inserting aggregation logic
INSERT INTO yourtable1 (state, month, id, sales)
SELECT
state,
month,
id,
SUM(sales)
FROM yourtable
GROUP BY state,
month,
id;
-----Fetching records
SELECT
*
FROM yourtable1;

timestampdiff() parameters error

I am using mysql version 5.6 on sql fiddle, and I'm trying to use timestampdiff() function to find the difference between the minimum value in the first column and the largest value in the second one in a table named Task as following
select TimeStampDiff(month, , max(Task.End_Date), min(Task.Start_Date));
but when I run this code I get the following error:
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ' months(max(End_Date)), months(min(Start_Date)))' at line 1
is it that timestampdiff() does not accept an aggregate function as a parameter ? and how can I solve this problem?
here's my complete fiddle
Try:
mysql> DROP TABLE IF EXISTS `Task`;
Query OK, 0 rows affected, 1 warning (0.00 sec)
mysql> CREATE TABLE IF NOT EXISTS `Task` (
-> `ID` INT NOT NULL,
-> `Pro_ID` INT NOT NULL,
-> `Start_Date` DATE,
-> `End_Date` DATE,
-> `Description` VARCHAR(255),
-> PRIMARY KEY (`ID`)
-> );
Query OK, 0 rows affected (0.00 sec)
mysql> INSERT INTO `Task` VALUES
-> (1, 1, '2017-01-01', '2017-02-01', "no-Description-yet"),
-> (2, 1, '2017-01-01', '2017-02-01', "no-Description-yet"),
-> (3, 1, '2017-01-01', '2017-06-01', "no-Description-yet"),
-> (4, 2, '2017-01-01', '2017-03-01', "no-Description-yet"),
-> (5, 3, '2017-01-01', '2017-02-01', "no-Description-yet"),
-> (6, 4, '2017-01-01', '2017-03-01', "no-Description-yet");
Query OK, 6 rows affected (0.02 sec)
Records: 6 Duplicates: 0 Warnings: 0
mysql> SELECT
-> `Pro_ID`,
-> TIMESTAMPDIFF(MONTH, MIN(`Start_Date`), MAX(`End_Date`)) `MONTH_DIFF`
-> FROM `Task`
-> GROUP BY `Pro_ID`;
+--------+------------+
| Pro_ID | MONTH_DIFF |
+--------+------------+
| 1 | 5 |
| 2 | 2 |
| 3 | 1 |
| 4 | 2 |
+--------+------------+
4 rows in set (0.00 sec)
Example db-fiddle.

I have '0001/16' value in my MySQL Data Base. How can i write in where clause as '1/16' to select?

I have '0001/16' value in my MySQL Data Base. How can i write in where clause as '1/16' to select ?
Note : we cannot predict how many zeros before nonzero digit.
Hibernate Criteria will be more helpful
Mysql you could do this
MariaDB [sandbox]> SET #T = '001/16';
Query OK, 0 rows affected (0.00 sec)
MariaDB [sandbox]>
MariaDB [sandbox]> select #T
-> FROM DUAL
-> WHERE
-> concat(
-> REPLACE(SUBSTRING(#T,1,INSTR(#T,'/') - 1),'0','')
-> ,
-> substring(#t,INSTR(#T,'/'),length(#t) - 1)
-> )
-> = '1/16'
-> ;
+--------+
| #T |
+--------+
| 001/16 |
+--------+
1 row in set (0.00 sec)