SQL Query - Need help to run the last query - mysql

with hotels as (
select * from hotel_revenue_historical_full
union
SELECT * FROM projects.`db.2019`
union
SELECT * FROM projects.`2020`);
select * from hotels;
select stays_in_weekend_nights + stays_in_week_nights from hotels;
select arrival_date_year,hotel, sum ((stays_in_weekend_nights + stays_in_week_nights) * adr) as revenue from hotels group by arrival_year, hotel;

-- save the data into temptable
CREATE TEMPORARY TABLE hotels
select * from hotel_revenue_historical_full
union
SELECT * FROM projects.`db.2019`
union
SELECT * FROM projects.`2020`;
-- query needed information
select *, stays_in_weekend_nights + stays_in_week_nights from hotels;
select arrival_date_year,hotel, sum ((stays_in_weekend_nights + stays_in_week_nights) * adr) as revenue from hotels group by arrival_year, hotel;
-- drop temptable
DROP TEMPORARY TABLE hotels;
If the table hotel is not huge then you may add ENGINE = Memory to its definition which will improve the process.
Also I recommend you to use not UNION but UNION ALL.

Related

UNION SELECT is faster than a VIEW of the same query in MySQL

my Query is
select * from `database_1`.`table_name`
union all
select * from `database_2`.`table_name`;
this Query Run In 0.0074 - 0.0170 seconds
But when create View with this Query
create View `view_name` as
select * from `database_1`.`table_name`
union all
select * from `database_2`.`table_name`;
select * from `view_name`;
this Query Run In 0.0800 - 0.1200 seconds
Notice: this view is on tow databases.
Thanks

MySQL-extract a number from db and use it in same query

table 1 in my db has many columns including id and time. an id is sent to the server, then I have to extract its corresponding time (let's say t) from table and run a query like this:
SELECT * FROM(
(SELECT * FROM table1 WHERE time>t AND ...clause 1...) // query A
UNION
(SELECT * FROM table1 WHERE time>t AND ...clause 2...) // query B
) h LIMIT 24;
how to include a subquery in the query mentioned above which extracts t and makes it accessible by query A and query B?
I think you need Mysql WITH (Common Table Expression) here,
WITH CTE AS (
SELECT * FROM table1 WHERE time>t
)
SELECT * FROM (
(SELECT * FROM CTE AND ...clause 1...) // query A
UNION
(SELECT * FROM CTE AND ...clause 2...) // query B
) h LIMIT 24;

Php mysql bad query when displays on a table

there's my code that select 5 databases and display in a table, but the where statement not work
The where is ignored by the query.
SELECT *
FROM events
UNION ALL
SELECT * FROM eventstwo
UNION ALL
SELECT * FROM eventsthree
UNION ALL
SELECT * FROM eventsfour
UNION ALL
SELECT * FROM eventsfive where atender='$obj'
I suspect that you want the WHERE criteria to apply to every subquery in the union. If you want that, you'll have to add a WHERE clause to each subquery. But, if you really do want to use a single WHERE clause, you can wrap your union query and then subquery it:
SELECT *
FROM
(
SELECT * FROM events
UNION ALL
SELECT * FROM eventstwo
UNION ALL
SELECT * FROM eventsthree
UNION ALL
SELECT * FROM eventsfour
UNION ALL
SELECT * FROM eventsfive
) t
WHERE atender = '$obj';
Side note: Please use prepared statements in your PHP code wherever possible.
SELECT * FROM
( SELECT *
FROM events
UNION ALL
SELECT * FROM eventstwo
UNION ALL
SELECT * FROM eventsthree
UNION ALL
SELECT * FROM eventsfour
UNION ALL
SELECT * FROM eventsfive)
AS derived
WHERE atender='$obj'

How can I create a view with duplicate columns and merge them?

I have pm_message tables with 1~9, and I want to create a view to simplified the process of MySQL query.
What I have is
CREATE VIEW `pm_messages` AS
SELECT * FROM
`pm_messages_0`,
`pm_messages_1`,
`pm_messages_2`,
`pm_messages_3`,
`pm_messages_4`,
`pm_messages_5`,
`pm_messages_6`,
`pm_messages_7`,
`pm_messages_8`,
`pm_messages_9`;
I got error with douplicate column. There is no record is duplicate, I want to merge all of them in view, what should I do?
You have coded a colossal cross join. Depending on the number of rows, it probably wouldn't return before the universe suffers entropy heat death.
I'm almost certain you want a union:
CREATE VIEW `pm_messages` AS
SELECT * FROM `pm_messages_0` union all
SELECT * FROM `pm_messages_1` union all
SELECT * FROM `pm_messages_2` union all
SELECT * FROM `pm_messages_3` union all
SELECT * FROM `pm_messages_4` union all
SELECT * FROM `pm_messages_5` union all
SELECT * FROM `pm_messages_6` union all
SELECT * FROM `pm_messages_7` union all
SELECT * FROM `pm_messages_8` union all
SELECT * FROM `pm_messages_9`;
This will work if all tables have the same number and type of columns. If not, you'll have to explicitly select columns such that each select returns the same number and type of columns.

Search for the existance of many objects in a database

Say I have a database with 5 million users, with the columns
id (unsigned int, auto-increment), facebook_id (unsigned int), and name (varchar)
In a program, I have a list of a variable amount of users from a person's facebook friend list (generally ranging from 500-1200 different facebook ids).
What's the most efficient way to send a query to my database that returns the facebook_id's of all of the users where that same facebook_id exists in the database?
Pseudo-code:
$friends = array(12345, 22345, 32345, 42345, 52345, ... ~1000 more);
$q = mysql_query("SELECT * FROM users ...");
$friendsAlreadyUsingApp = parseQuery($q);
This is a topic of almost an endless number of articles, blogs, Q&As etc; and the essence of this problem is that it looks really simple - but isn't.
The heart of the problem is that the parameters looks like it should work using WHERE field IN() BUT it does not do that because the parameter is a single string that just happens to have lots of commas in it.
So, when that parameter is passed to SQL it is necessary to process that single string into multiple parts so that the field can be compared to each part. This is where it gets a little complex as not all database types have all the same features to handle this. MySQL for example does not have a table variable that MS SQL Server provides.
So. A simple method, for MySQL is this:
SET #param := '105,110,125,135,145,155,165,175,185,195,205';
SELECT
*
FROM Users
WHERE FIND_IN_SET(facebook_id, #param) > 0
;
FIND_IN_SET Return the index position of the first argument
within the second argument
Just how well this scales in your database I cannot tell, it might not be acceptable for parameters containing 1000+ id's.
So if text processing like FIND_IN_SET is too slow, then each id needs to be broken out from the parameter and inserted into a table. That way the resulting table can be used through an INNER JOIN to filter the users; but this requires a table and inserts which take time, and there may be concurrency issues if more than one user is attempting to use that table at the same time.
Using the following sets-up a table of 10,000 integers (1 to 10,000)
/* Create a table called Numbers */
CREATE TABLE `Numbers`
(
`Number` int PRIMARY KEY
);
/* use cross joins to create 10,000 integers from 1 & store into table */
INSERT INTO Numbers (Number)
select 1 + (a.a + (10 * b.a) + (100 * c.a) + (1000 * d.a)) as N
from (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as a
cross join (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as b
cross join (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as c
cross join (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as d
;
This "utility table" can then be used to divide a comma separated parameter into a derived table of the individual integers, and this then used in an INNER JOIN to your users table will provide the wanted result.
SET #param := '105,110,125,135,145,155,165,175,185,195,205';
SET #delimit := ',';
SELECT
users.id
, users.facebook_id
, users.name
FROM users
INNER JOIN (
SELECT
CAST(SUBSTRING(iq.param, n.number + 1, LOCATE(#delimit, iq.param, n.number + 1) - n.number - 1) AS UNSIGNED INTEGER) AS itemID
FROM (
SELECT
concat(#delimit, #param, #delimit) AS param
) AS iq
INNER JOIN Numbers n
ON n.Number < LENGTH(iq.param)
WHERE SUBSTRING(iq.param, n.number, 1) = #delimit
) AS derived
ON users.facebook_id = derived.itemID
;
This query can be used as the basis for a stored procedure which might be easier for you to call from PHP.
See this SQLFiddle demo