Query Multiple table with same structure - php

I have a few tables with the same structure built and wanted to query them at once using PHP MYSQL.
The challenging part that I face was to query x tables where I do not know how many of them there. (Assuming user will select the tables on UI perspective). The reason of this is to output them into a csv format.
For example:-
Date, xTable, yTable, zTable, ....
==============================b
bla 1 2 3
bla 4 3 5
...
...
How can I modify below query to cater for above needs? (The query needs to be flexible enough to query multi table).
SELECT created_dt,
xTable FROM needToQueryMultiTable WHERE created_dt BETWEEN ? AND ?

You can create a view of all possible tables:
create v_tables as
select 'table1' as which, t.*
from table1 t
union all
select 'table2' as which, t.*
from table2 t
. . .;
Then, you can select from the view.
In MySQL this is not particularly efficient, because all the tables will still need to be read. However, for smaller tables this could be a reasonable solution.
You should ask yourself why you have identically structured tables in the databases. In general, these should be combined into a single table. For performance, you can partition the table.

Related

How get table with references other table in yii2?

i have multiple table that join together and i need one query and get all references too ! is that possible in yii2??
get them in hierarchy array ??
How ???
Is it possible to do not use join???
thanks for your help!!!!
If you created the model classes for each table using Gii and selected to create the relations in the generated models, you can do something like the following.
1) In your Countries model just change the method that declares the relationship with Airports like this:
public function getAirports() {
return $this->hasMany(Airports::className(), ['country_id' => 'id'])->with('airlines');
}
2) When you do the query for the countries and you need to have the related airports, airlines and flightbooked do it like this:
$countries = Countries::find()
->where('something = something_else')
->with('airports')
->with('flightbooked')
->all();
This way you will get all the related models populated with way less queries to the database than using lazy-loading.
I just wanted to give a small suggestion:
As you are maintaining the relations in the tables and if you have generated your code using Gii, then that will generate the joins for you. You can then access any column of any table easily.
But I think UNION may not be an alternative to JOIN.
Maybe u can use union all for this. with this operator, you can concatenate the result sets from multiple queries together, preserving all of the rows from each. Note that a UNION operator (without the ALL keyword) will eliminate any "duplicate" rows which exist in the resultset. The UNION ALL operator preserves all of the rows from each query (and will likely perform better since it doesn't have the overhead of performing the duplicate check and removal operation).
The number of columns and data type of each column must match in each of the queries. If one of the queries has more columns than the other, we sometimes include dummy expressions in the other query to make the columns and datatypes "match". Often, it's helpful to include an expression (an extra column) in the SELECT list of each query that returns a literal, to reveal which of the queries was the "source" of the row.
SELECT 'col1' AS source, col23, col343, col33, d FROM table1 WHERE ...
UNION ALL
SELECT 'col2', t2.fee, table2.fi, table2.fo, 'fum' FROM table2 JOIN table3 ON ...
UNION ALL
SELECT 'col3', '1', '2', buckle, my_shoe FROM table4
You can wrap a query like this in a set of parenthesis, and use it as an inline view (or "derived table", in MySQL lingo), so that you can perform aggregate operations on all of the rows. e.g:
select one.a
, SUM(one.b)
FROM (
SELECT 'q1' AS source, a, b, c, d FROM t1
UNION ALL
SELECT 'q2', t2.fee, t2.fi, t2.fo, 'fum' FROM t2
) one
GROUP BY one.a
ORDER BY one.a
But i think joining tables more suitable. Hope help you

PHP array_diff VS mysql NOT IN

I tried to compare two zipcode columns between two tables to see if values were missing in the second one.
I first wanted to do it with mysql, my query was something like
'SELECT code FROM t1 WHERE t1 NOT IN (select code FROM t2)'
But it was really slow so I tried another way :
I made two select, and then compared the results with array_diff().
With mysql : few minutes, and sometimes crash
With PHP : less than 1 second.
Can someone explain these differences ?
Is my SQL query wrong ?
If your main table has 50k rows, using a sub select in your query will result into 1 + 50k executions of selects. One for the first table, and 50k selects, one for each row. The server compares the row with your sub select that is reloaded every time iterating the main table. This is why your sql code takes its time and it also may be a huge memory problem as well.
See serjoschas information about joins to fix it in sql, it should be even faster that your php solution.
Checking which values are missing within a table (compared to another) can easily be done with a LEFT or RIGHT JOIN they are just made for actions like this.. alternatively take a look at this: How to Find Missing Value Between Two Mysql Tables – serjoscha
One solution to:
SELECT code FROM t1
WHERE code NOT IN ( SELECT code FROM t2 )
will be:
SELECT t1.code
FROM t1
LEFT JOIN t2
ON t1.code = t2.code
WHERE t2.code is null
Have a try. Also have a look on indexing as Cyclone suggests:
If you don't have an index you should definitly add one since this will speed up your query. You could add an index like this: ALTER TABLE ADD INDEX code_idx (code) this should be done for both tables. If you then were to execute EXPLAIN for the query you would see something like Using where; Using index; Using join buffer which is good – Cyclone
Indexing speeds up your query. If the table only provides one column, searching an index table with the same content as the source table will be exactly the same and redundant. Otherwise I strongly recommend indexing the code column of t2 which leads to a high increase of performance and less memory consumtion.

How to create pagination that based on two sql queries? (PHP)

I have page that display information from two different tables , and for that I have two queries.
There is no related info between these two tables.
Since both queries may contain a lot of information, I need create pagination.
BUT I don't want two separate paginations, I want only one that will contain results from query 1 and query 2 together.
How can I do that?
The only idea I have is to fetch all info of both queries into arrays, then combine the arrays into one, then create pagination that based on that array.
That of course would not help save resources.
You could use a union - the columns you're displaying must line up, so something like this should work:
select
col1 col1_alias,
col2 col2_alias,
...
from
table1
where
...
union
select
col1,
col2,
...
from
table2
where
...
order by col1_alias, col2_alias
limit 10
Basically the union will pull all the data together, and the order by and limit will apply to the whole result set.
The names of the columns don't need to match in the second select, but use column names from the first select for your order by (or create aliases, which is probably more readable depending on your dataset).

See which table a result is in

I took over managing an internal website for the company that I'm working for and I need to get data out of a mysql database. The problem that I'm encountering is that the data is in 6 different tables, all with the same fields but the rows are all unique (the row starts in one table and then gets completely moved to a different table after it is processed by an employee).
Is there an easy way to query against all 6 at once? It would also be useful to be able to retrieve the title of the table it came from.
I'm using PHP to run the query and display it. Would it be better to create another table that defines where all the rows are, have a unique id and then another field for which table it's in?
To complete this query, use union all:
select
'Table1' as TableName,
*
from
Table1
union all
select
'Table2',
*
from
Table2
union all
select
'Table3',
*
from
Table3
...and so on
For better database design, you would want to either have one table with all the rows in it, and a designated Status table where you can link a StatusID column to that says what status that given row is in. A table for each stage in a process is a poor design and will only lead to massive headaches down the road.
If you can't reorganize the tables so that you have just one with all rows and a marker for where in the process they are, I would go for a UNION-approach. Ie:
SELECT 'Data from Table 1', t1.field1, ...
FROM Table1 t1
UNION
SELECT 'Data from Table 2', t2.field1, ...
FROM Table2 t2
UNION
(Table3, 4, 5 and 6 in the same manner)
....
That way you can see where the data is originating from and you get all 6 at once. Just remember that you have to have the exact same field list in all parts of the UNION.
You could create a code generator that generates SQL statements to query the 6 tables. The generator would create a UNION of 6 selects and add a "table" column to each select with a constant value equal to the name of the table queried. That would make writing the statements easy, though I wouldn't say that writing the generator would be.

Merging similar tables in SQL part 2

I think people were reluctant to help me last time because I didn't want to post up the columns, but I'm eager to solve this, so I'm putting aside my better judgement and laying it bare.
OK, I have two similar tables, and I'm using MySQL, and PHP to generate the tables. So far I have 3 tables:
CPE:
fastethernet00,subnet00,fastethernet01,subnet01,hsrp,vip,bgp,bgp_neighbor,remote_as,bgp_customer_net,next_hop,loopback,cpe,hostname,cpe_cust_index,int_next_hop_1,int_next_hop_2,voice,solution
Liverpool:
apn1,apn2,apn3,apn4,apn5,customer,vpi_vci,vlan1,cust_index,RADIUS,nexthop,atinterface1,atinterface2,feinterface1,feinterface2,spinterface1,spinterface2,ip_address_range1,ip_address_range2,handset_address_range1,handset_address_range2,handset_address_range3,handset_address_range4,handset_address_range5,handset_address_range6,handset_address_range7,handset_address_range8,handset_address_range9,handset_address_range10,handset_address_range11,handset_address_range12,handset_address_range13,handset_address_range14,handset_address_range15,handset_address_range16,DNS_Server1,DNS_Server2,OLVDMVPN,live
Greenwich:
apn_1,apn_2,apn_3,apn_4,apn_5,customer_,vpi_vci_,vlan_1,cust_index_,RADIUS_,nexthop_,atinterface_1,atinterface_2,feinterface_1,feinterface_2,spinterface_1,spinterface_2,ip_address_range_1,ip_address_range_2,handset_address_range_1,handset_address_range_2,handset_address_range_3,handset_address_range_4,handset_address_range_5,handset_address_range_6,handset_address_range_7,handset_address_range_8,handset_address_range_9,handset_address_range_10,handset_address_range_11,handset_address_range_12,handset_address_range_13,handset_address_range_14,handset_address_range_15,handset_address_range_16,DNS_Server_1,DNS_Server_2,OLVDMVPN_,live_
The first step I need to accomplish is linking Greenwich to Liverpool via apn_1/apn1. The same record won't necessarily be on both, and there may even be duplicates. The php I'm using to create this table is throwing up a syntax error around the UNION ALL:
mysql_query ("CREATE TABLE Both (
SELECT * FROM `Greenwich` left outer join Liverpool on Greenwich.apn_1 = Liverpool.apn1
UNION ALL
SELECT * FROM Greenwich
RIGHT OUTER JOIN Liverpool on Greenwich.apn_1 = Liverpool.apn1 where Greenwich.apn_1 is null)")
Can anyone see what's wrong with that?
Afterwards, I need to then link the resultant table to cpe_cust_index via cust_index/cust_index_, so ideally I think I need to merge these cells. If these cells are present in Greenwich and Liverpool they will always be the same.
Thanks in advance!
The answer is the 3rd way described here, using a "mutex (mutually exclusive) table
http://www.xaprb.com/blog/2006/05/26/how-to-write-full-outer-join-in-mysql/
This plus a filter give me exactly what I need. Now I just have to merge the index fields together, and apn 1 fields together.
Try naming all the columns that you want to select and alias then using AS so that they match. Union does not like column name mismatches.
Eg.
Select col1 as col1, col2 as col2 from table1
Union
Select col-1 as col1, col-2 as col2 from table2

Categories