MySQL with monthly tables and monthly joins - mysql

I am an trainee as a software developer. I have a question: How can I access to multiple tables with select and join?
The name of the main-tables are like:
logs_0215
logs_0315
logs_mmyy -> m = month; y = year
The name of the timestamp-tables are like:
timestamp_0215
timestamp_0315
timestamp_mmyy -> m = month; y = year
My query which works only for one table is like:
SELECT a.id, b.stamp, c.name AS portal, d.name AS company, e.name AS protocol, a.value
FROM logs_0315 AS a
LEFT JOIN timestamp_0315 AS b ON a.time_id = b.id
LEFT JOIN portale AS c ON a.portal_id = c.id
LEFT JOIN companies AS d ON a.comp_id = d.id
LEFT JOIN proocols AS e ON a.prot_id = e.id
WHERE b.stamp BETWEEN '2015-05-01' AND '2015-06-25'
How can I access to all tables which contains logs_mmyy with its timestamp?
Thank you for your help in advance.
Yours sincerely
t.koelpin

You would have to explicitly identify each table; each table has to be identified by name in a FROM clause. SQL does not support wildcard pattern matching for identifiers (table names, column names, etc.).
Given what you've posted, it looks like you could use a UNION ALL set operator to combine results from multiple SELECT statements as a single query:
SELECT a.id, ...
FROM logs_0315 a
LEFT JOIN timestamp_0315 AS b ON a.time_id = b.id
...
WHERE b.stamp BETWEEN '2015-05-01' AND '2015-06-25'
UNION ALL
SELECT a.id, ...
FROM logs_0415 a
LEFT JOIN timestamp_0415 AS b ON a.time_id = b.id
...
WHERE b.stamp BETWEEN '2015-05-01' AND '2015-06-25'
UNION ALL
SELECT a.id, ...
FROM logs_0515 a
LEFT JOIN timestamp_0515 AS b ON a.time_id = b.id
...
WHERE b.stamp BETWEEN '2015-05-01' AND '2015-06-25'
If you need an ORDER BY on the combined result, you can enclose each SELECT statement in parens. Like this:
( SELECT a.id, ...
FROM logs_0315 a
LEFT JOIN timestamp_0315 AS b ON a.time_id = b.id
...
WHERE b.stamp BETWEEN '2015-05-01' AND '2015-06-25'
)
UNION ALL
( SELECT a.id, ...
FROM logs_0415 a
LEFT JOIN timestamp_0415 AS b ON a.time_id = b.id
...
WHERE b.stamp BETWEEN '2015-05-01' AND '2015-06-25'
)
UNION ALL
( SELECT a.id, ...
FROM logs_0515 a
LEFT JOIN timestamp_0515 AS b ON a.time_id = b.id
...
WHERE b.stamp BETWEEN '2015-05-01' AND '2015-06-25'
)
ORDER BY ...
In order to make this dynamic, to get all tables of the pattern logs_mmyy, you could query information_schema.tables and get the list of tables, and then use that to dynamically generate a statement as above. This approach requires (at a minimum) two separate SQL statements. It's not possible to achieve this type of result in a single SQL statement.

Related

mysql left join need order by and group by on right table

for simple, I write an example like this
select
a.xx,
a.xx,
... -- all table a's field
b.date,
b.money
c.date,
c.money,
d.date,
d.money,
e.date,
e.money
from
a
left join b on a.id = b.a_id
left join c on a.id = c.a_id
left join d on a.id = d.a_id
left join e on a.id = e.a_id
where ... -- some condition
limit 10
In this sql, table b and c is one to one to table a
but table d and e is not that.
With no optimization. table d and e while seem like this
-- ... sql before
left join
(
select * from
(select * from d order by date desc) as temp
group by a_id
) as d on a.id = d.a_id
left join
(
select * from
(select * from e order by id desc) as temp
group by a_id
) as e on a.id = e.a_id
-- ... sql after
But in fact, it is very slow when running this.
table d was a new table, it didn't has larges of data yet(it will be large in future).
table e had million now. subquery of table e make my sql very slow. How to optimization it?

How to use data from WHERE query MYSQL

I have this MySQL query:
SELECT * FROM A
LEFT JOIN B
ON B.id = A.id
LEFT JOIN C
ON C.other = A.other
WHERE
(SELECT SUM(C.quantity) FROM C WHERE C.other = A.other) < A.quantity
Is any way to get values from SELECT from WHERE clause? For example for PHP to use? Something like:
WHERE
(SELECT SUM(C.quantity) FROM C WHERE C.other = A.other) AS quantity < A.quantity
I need to compare this two values in mysql and then i need them both in my script. I can of course put this subquery into first SELECT - but i belive there is better way to do this than repeat code in many places.
You could do that as follows:
SELECT A.*, B.*, C.*, D.sumq
FROM A
LEFT JOIN B
ON B.id = A.id
LEFT JOIN C
ON C.other = A.other
LEFT JOIN (
SELECT other, SUM(quantity) sumq
FROM C
GROUP BY other
) AS D
ON D.other = A.other
WHERE COALESCE(D.sumq, 0) < A.quantity

how to count the two count function's return value in once sql query

I have three tables A,B,C.Their relation is A.id is B's foreign key and B.id is C's foreign key.I need to sum the value when B.id = C.id and A.id = B.id ,I can count the number by query twice. But now I need some way to count the summation just once time !
My inefficient solution
select count(C.id) from C,B where C.id = B.id; //return the value X
select count(A.id) from C,B where A.id = B.id; //return the value Y
select X + Y; // count the summation fo X and Y
How can I optimize ? Thks! :)
PS:
My question is from GalaXQL,which is a SQL interactive tutorial.I have abstract the problem,more detail you can check the section 17.SELECT...GROUP BY... Having...
You can do these things in one query. For instance, something like this:
select (select count(*) from C join B on C.id = B.id) +
(select count(*) from C join A on C.id = A.id)
(Your second query will not parse because A is not a recognized table alias.)
In any case, if you are learning SQL, the first thing you should learn is modern join syntax. The implicit joins that you are using were out of date 15 years ago and have been part of the ANSI standard for over 20 years. Learn proper join syntax.
Try Like This
select sum(cid) (
select count(*) as cid from C join B on C.id = B.id
union all
select count(*) as cid from A join B on A.id = B.id ) as tt
try this one:
select
(select count(*) from C join B on C.id = B.id)
union
(select count(*) from C join A on C.id = A.id)

Incorrect id returned on LEFT JOIN in Mysql statement

I need to get the id and timestamps of table sellers and all other columns (without knowing the column names) from these results returned from this MySql statement:
SELECT * FROM sellers a
LEFT JOIN users b ON a.user_id = b.id
LEFT JOIN country_types c ON a.country_type_id = c.id
LEFT JOIN language_types d ON a.language_type_id = d.id
WHERE a.email=?
The seller id though is incorrectly set because users, country_types, and language_types all have a value id. How can I set seller_id and seller_timestamp? I tried this but it is incorrect:
SELECT a.id seller_id, a.timestamp seller_timestamp, * FROM sellers a ...
You want this:
SELECT a.id as seller_id, a.timestamp as seller_timestamp, a.*, b.*, c.*, d.*
FROM sellers a
LEFT JOIN users b ON a.user_id = b.id
LEFT JOIN country_types c ON a.country_type_id = c.id
LEFT JOIN language_types d ON a.language_type_id = d.id
WHERE a.email=?
Im not sure but try alias, for example:
a.id AS seller_id
and etc.
In joins you can't select other columns in this way:
SELECT a.id seller_id, a.timestamp seller_timestamp, * FROM sellers a...
You need to write required column names.

MySQL GROUP BY performance issue

This is the query I'm performing (without some Joins that are not relevant):
SELECT a.*, c.id
FROM a
LEFT OUTER JOIN b ON a.id = b.id_anunciante
LEFT OUTER JOIN c ON c.id = b.id_rubro
GROUP BY a.id
Each row of "a" is linked with 1 to 5 rows in "b".
The problem is that GROUP BY has performance issues (it takes 10x or more using GROUP BY than not using it). I need to retrieve only one row of each member in "a".
How can I make this faster?
edit: I need to be able to filter by a.id AND/OR c.id. The resultset I should be getting is only 1 row per "valid" member of "a", meaning the rows that match the constraints. Rows that don't match the filters shouldn't be returned.
In my original query, this would be done this way:
SELECT a.*, c.id
FROM a
LEFT OUTER JOIN b ON a.id = b.id_anunciante
LEFT OUTER JOIN c ON c.id = b.id_rubro
WHERE c.id = 1
OR a.id = 1
GROUP BY a.id
a.id, b.id_anunciante, b.id_rubro, c.id are all indexes.
SELECT a.*,
(
SELECT c.id
FROM b
JOIN с
ON c.id = b.id_rubro
WHERE b.id_anunciante = a.id
-- add the ORDER BY condition to define which row will be selected.
LIMIT 1
)
FROM a
Create the index on b (id_anunciante) for this to work faster.
Update:
You don't need the OUTER JOINs here.
Rewrite your query as this:
SELECT a.*, c.id
FROM a
JOIN b
ON b.id_anunciante = a.id
JOIN c
ON c.id = b.id_rubro
WHERE a.id = 1
UNION ALL
SELECT a.*, 1
FROM a
WHERE EXISTS
(
SELECT NULL
FROM c
JOIN b
ON b.id_rubro = c.id
WHERE c.id = 1
AND b.id_anunciante = a.id
)
Add ORDER BY NULL to avoid the implicit sorting MySQL does when doing a group by.
I suppose you have indexes/PKs on a.id, b.id_anunciante, b.id_rubro and c.id ? I guess you could try adding a composite index on (b.id_anunciante, b.id_rubro) if your mysql version is not able to do an index merge.