web-dev-qa-db-fra.com

Comment effectuer une requête sur une liste dynamique de tables?

J'ai une base de données appelée (Conntrack) avec une quantité inconnue de tables.Je disposez d'une table statique "tabidx" qui a une colonne "date".

Le tableau suivant est statique et son nom est Tabidx qui fournit une référence à d'autres tables:

 tabidx (table):
 +------------+
 |    date    |
 +------------+
 | 2015-04-25 |
 | 2015-04-26 |
 | 2015-04-27 |
 | 2015-04-28 |
 | 2015-04-29 |
 +------------+

Vous trouverez ci-dessous l'exemple des tables référencées de 'Tabidx' 'Date':

2015-04-25 (table):                             
+---------------------------------------------+    
| time      | username | srcip      | scport  |    
+---------------------------------------------+    
| 19:20:00  | L001000  | 10.10.10.1 |  1304   |   
| 19:20:00  | L001001  | 10.10.10.2 |  1640   |    
| 19:20:01  | L001002  | 10.10.10.3 |  2001   |    
+---------------------------------------------+ 

2015-04-26 (table):                             
+---------------------------------------------+    
| time      | username | srcip      | scport  |    
+---------------------------------------------+    
| 19:21:00  | L001000  | 10.10.10.1 |  1304   |   
| 19:21:00  | L001001  | 10.10.10.2 |  1640   |    
| 19:21:01  | L001002  | 10.10.10.3 |  2001   |    
+---------------------------------------------+ 

Je voudrais énumérer le gestionnaire les tables disponibles qui existent dans Tabidx et comptent le nombre d'utilisateurs que nous avons dans toutes les tablees s'ils sont référencés dans Tabidx. Donc, si le gestionnaire a demandé:

$_GET['fromdate'] = '2015-05-25'  
$_GET['todate'] = date(); //till today date 2015-04-30
$_GET['username'];
$_GET['srcport'];
$_GET['srcip'];

J'aimerais que la sortie correspondre aux lignes MySQL en fonction de la demande ci-dessus. Par exemple:

OUTPUT: [available tables WHERE username=L00100]
+-------------------------------------------+    
| Date and Time | username | srcip | scport |     
+-------------------------------------------+    
|   2015-04-25  | L001000  |   %   |   %    |   
|   2015-04-26  | L001000  |   %   |   %    |    
|   2015-04-27  | L001000  |   %   |   %    |    
+-------------------------------------------+

Comment puis-je énumérer ou sélectionner toutes les tables que l'on trouve dans Tabidx.? Je ne sais pas comment utiliser des déclarations préparées dans MySQL.

Je sais que la première étape devrait lister les tables disponibles. Et si quelqu'un veut demander aux tableaux disponibles avec un utilisateur spécifique comme "L002000", nous ne devrions pas répertorier les tables car nos tables dynamiques n'ont pas ce nom d'utilisateur.

$db = new dB();

$_GET['fromdate'] = ( isset($_GET['fromdate']) && isValideDate($_GET['fromdate']) ) ?       $_GET['fromdate'] : $todayDate;
$_GET['todate'] = ( isset($_GET['todate']) && isValideDate($_GET['todate']) ) ?  $_GET['todate'] : $todayDate;
$sql_fromdate = " date >= '{$_GET['fromdate']}' AND";
$sql_todate = " date >= '{$_GET['todate']}'";

$result = $db -> query("SELECT date FROM tabidx WHERE $sql_fromdate $sql_todate");
$_GET['username'] = ( isset($_GET['username']) && $_GET['username'] !='' ) ?                           ....$_GET['username'] : '';


if($result)
{
    // Loop through the available tables that are included in table 'tabidx' 

    while( $b_row = $result -> fetch_assoc() )
    {
        $table_name = $db_row['date'];

        // Query the table and count the number of rows according to the requested $_GET Method

        $result2 = $b -> query("SELECT count(*) FROM $table_name WHERE username LIKE '{$_GET['username']}%'");
        $num_row = $result2 -> fetch_row();

        // Check if the number of rows are greater than zero
        // then show the row of $result to the user

        if($num_row[0] > 0)
        {
            echo '<tr>';
            echo '<td>$table_name</td>';
            echo "<td>{$_GET['username']}</td>";
            echo '<td></td>';
            echo '<td></td>';
            echo '</tr>';
        }
    }

}

J'ai réussi à faire une solution temporaire, mais ce que je sais que cette solution est si mauvaise et que je ne suis pas celui qui a créé cette structure. Nous pourrions atteindre jusqu'à 360 tables pendant une année.

Pouvons-nous simplement faire tout le travail en utilisant une requête MySQL.?

1
Ghassan

Tout cela aurait pu être accompli avec la base de données Information_Schema

Les noms de table sont dans l'information_schema

SELECT table_name FROM information_schema.tables
WHERE table_schema='conntrack';

Vous pouvez ensuite aligner les tables qui existent contre la table tabidx

SELECT B.table_name FROM (SELECT date FROM tabidx) A
INNER JOIN (SELECT table_name FROM information_schema.tables
WHERE table_schema='conntrack') B ON A.date = B.table_name;

Avec ces noms de table, configurez une longue requête contre toutes les tables de conntrack

Requête proposée

SET @fromdate = '2015-04-25';
SET @todate = CURRENT_DATE();
SET @given_username='L001000';
SELECT
    GROUP_CONCAT(qry SEPARATOR ' UNION ')
    INTO @sql
FROM
(
    SELECT CONCAT('SELECT ',QUOTE(table_name),' as "Date and Time"',
    ',username,''%'' srcip,''%'' scport FROM `',table_name,
    '` WHERE username=',QUOTE(@given_username)) qry
    FROM
    (
        SELECT BB.table_name FROM
        (
            SELECT date FROM tabidx
            WHERE date>=@fromdate AND date<=@todate
        ) AA
        INNER JOIN
        (
            SELECT table_name FROM information_schema.tables
            WHERE table_schema='conntrack'
        ) BB ON AA.date = BB.table_name
    ) A
) B;
PREPARE s FROM @sql; EXECUTE s; DEALLOCATE PREPARE s;

Exemple de données (de votre question)

DROP DATABASE IF EXISTS conntrack_sample;
CREATE DATABASE conntrack_sample;
USE conntrack_s
CREATE TABLE tabidx (date date, PRIMARY KEY (date));
INSERT INTO tabidx VALUES 
('2015-04-25'),('2015-04-26'),('2015-04-27'),
('2015-04-28'),('2015-04-29');
SELECT * FROM tabidx;
CREATE TABLE `0000-00-00`
(
    time time,username CHAR(7),
    srcip CHAR(15),scport INT,
    PRIMARY KEY (username,time)
);
CREATE TABLE `2015-04-25` LIKE `0000-00-00`;
CREATE TABLE `2015-04-26` LIKE `0000-00-00`;
CREATE TABLE `2015-04-27` LIKE `0000-00-00`;
CREATE TABLE `2015-04-28` LIKE `0000-00-00`;
CREATE TABLE `2015-04-29` LIKE `0000-00-00`;
INSERT INTO `2015-04-25` VALUES
('19:20:00','L001000','10.10.10.1',1304),
('19:20:00','L001001','10.10.10.2',1640),
('19:20:01','L001002','10.10.10.3',2001);
INSERT INTO `2015-04-26` VALUES
('19:21:00','L001000','10.10.10.1',1304),
('19:21:00','L001001','10.10.10.2',1640),
('19:21:01','L001002','10.10.10.3',2001);

Exemple de données chargées

mysql> DROP DATABASE IF EXISTS conntrack_sample;
Query OK, 0 rows affected, 1 warning (0.00 sec)

mysql> CREATE DATABASE conntrack_sample;
Query OK, 1 row affected (0.00 sec)

mysql> USE conntrack_sample
Database changed
mysql> CREATE TABLE tabidx (date date, PRIMARY KEY (date));
Query OK, 0 rows affected (0.03 sec)

mysql> INSERT INTO tabidx VALUES
    -> ('2015-04-25'),('2015-04-26'),('2015-04-27'),
    -> ('2015-04-28'),('2015-04-29');
Query OK, 5 rows affected (0.02 sec)
Records: 5  Duplicates: 0  Warnings: 0

mysql> SELECT * FROM tabidx;
+------------+
| date       |
+------------+
| 2015-04-25 |
| 2015-04-26 |
| 2015-04-27 |
| 2015-04-28 |
| 2015-04-29 |
+------------+
5 rows in set (0.00 sec)

mysql> CREATE TABLE `0000-00-00`
    -> (
    ->     time time,username CHAR(7),
    ->     srcip CHAR(15),scport INT,
    ->     PRIMARY KEY (username,time)
    -> );
Query OK, 0 rows affected (0.03 sec)

mysql> CREATE TABLE `2015-04-25` LIKE `0000-00-00`;
Query OK, 0 rows affected (0.05 sec)

mysql> CREATE TABLE `2015-04-26` LIKE `0000-00-00`;
Query OK, 0 rows affected (0.02 sec)

mysql> CREATE TABLE `2015-04-27` LIKE `0000-00-00`;
Query OK, 0 rows affected (0.02 sec)

mysql> CREATE TABLE `2015-04-28` LIKE `0000-00-00`;
Query OK, 0 rows affected (0.05 sec)

mysql> CREATE TABLE `2015-04-29` LIKE `0000-00-00`;
Query OK, 0 rows affected (0.05 sec)

mysql> INSERT INTO `2015-04-25` VALUES
    -> ('19:20:00','L001000','10.10.10.1',1304),
    -> ('19:20:00','L001001','10.10.10.2',1640),
    -> ('19:20:01','L001002','10.10.10.3',2001);
Query OK, 3 rows affected (0.00 sec)
Records: 3  Duplicates: 0  Warnings: 0

mysql> INSERT INTO `2015-04-26` VALUES
    -> ('19:21:00','L001000','10.10.10.1',1304),
    -> ('19:21:00','L001001','10.10.10.2',1640),
    -> ('19:21:01','L001002','10.10.10.3',2001);
Query OK, 3 rows affected (0.00 sec)
Records: 3  Duplicates: 0  Warnings: 0

mysql>

Requête proposée exécutée

mysql> SET @fromdate = '2015-04-25';
Query OK, 0 rows affected (0.00 sec)

mysql> SET @todate = CURRENT_DATE();
Query OK, 0 rows affected (0.02 sec)

mysql> SET @given_username='L001000';
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT
    ->     GROUP_CONCAT(qry SEPARATOR ' UNION ')
    ->     INTO @sql
    -> FROM
    -> (
    ->     SELECT CONCAT('SELECT ',QUOTE(table_name),' as "Date and Time"',
    ->     ',username,''%'' srcip,''%'' scport FROM `',table_name,
    ->     '` WHERE username=',QUOTE(@given_username)) qry
    ->     FROM
    ->     (
    ->         SELECT BB.table_name FROM
    ->         (
    ->             SELECT date FROM tabidx
    ->             WHERE date>=@fromdate AND date<=@todate
    ->         ) AA
    ->         INNER JOIN
    ->         (
    ->             SELECT table_name FROM information_schema.tables
    ->             WHERE table_schema='conntrack_sample'
    ->         ) BB ON AA.date = BB.table_name
    ->     ) A
    -> ) B;
Query OK, 1 row affected, 1 warning (0.00 sec)

mysql>

Sortie de requête proposée

mysql> PREPARE s FROM @sql; EXECUTE s; DEALLOCATE PREPARE s;
Query OK, 0 rows affected (0.00 sec)
Statement prepared

+---------------+----------+-------+--------+
| Date and Time | username | srcip | scport |
+---------------+----------+-------+--------+
| 2015-04-25    | L001000  | %     | %      |
| 2015-04-26    | L001000  | %     | %      |
+---------------+----------+-------+--------+
2 rows in set (0.00 sec)

Query OK, 0 rows affected (0.00 sec)

mysql>

ESSAIE !!!

Remarque: Voici ce que @SQL a

mysql> SELECT @sql\G
*************************** 1. row ***************************
@sql: SELECT '2015-04-25' as "Date and Time",username,'%' srcip,'%' scport FROM `2015-04-25` WHERE username='L001000' UNION SELECT '2015-04-26' as "Date and Time",username,'%' srcip,'%' scport FROM `2015-04-26` WHERE username='L001000' UNION SELECT '2015-04-27' as "Date and Time",username,'%' srcip,'%' scport FROM `2015-04-27` WHERE username='L001000' UNION SELECT '2015-04-28' as "Date and Time",username,'%' srcip,'%' scport FROM `2015-04-28` WHERE username='L001000' UNION SELECT '2015-04-29' as "Date and Time",username,'%' srcip,'%' scport FROM `2015-04-29` WHERE username='L001000'
1 row in set (0.00 sec)

mysql>
3
RolandoMySQLDBA