8
votes

MySQL: Est-il possible de "remplir" une sélection avec des valeurs sans table?

Je dois afficher le total des «commandes» pour chaque année et chaque mois. Mais pendant quelques mois, il n'y a pas de données, mais je veux afficher ce mois-ci (avec une valeur totale de zéro). Je pourrais faire des "mois" helpertables avec 12 records pour chaque année, mais peut-être un moyen d'avoir une gamme de mois, sans introduire une nouvelle table?

Quelque chose comme: p>

SELECT CONCAT(MONTHNAME(datetime), ' ' , YEAR(datetime)) AS YearMonth,
       MONTH(datetime) AS Month,
       YEAR(datetime) AS Year 
FROM (
    select (curdate() - INTERVAL (a.a + (10 * b.a) + (100 * c.a)) MONTH) as datetime
    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
    LIMIT 120
) AS t
ORDER BY datetime ASC 


3 commentaires

Dans SQL Server, vous pouvez utiliser des CTES récursives ou des CTES croisées croisées pour le faire. Je suppose que vous pouvez sélectionner une table suffisamment grande et utiliser des variables utilisateur.


Pouvez-vous donner un peu plus d'informations sur votre table (s)?


@Jonny Fondamentalement, il n'y a que 1 tableau: commandes, qui contient un champ de date. Maintenant, j'ai besoin d'une liste de combien de commandes il y a eu chaque mois à compter de janvier 2000. Mais pendant quelques mois, il n'y a aucune commande. Mais je veux que ces mois apparaissent dans la liste. J'ai donc besoin d'une deuxième table, qui détient tous les mois de janvier 2000, puis rejoignez-le avec la table des commandes.


9 Réponses :


3
votes

Vous pouvez simplement remplir les mois manquants après avoir effectué votre requête dans votre logique d'application.


0 commentaires

6
votes

Vous pouvez essayer quelque chose comme ça xxx


0 commentaires

0
votes

Créer une table (par exemple, TblMonths ) qui inclut tous les 12 mois et utilisez un rejoindre (ou Joindre droit rejoindre ) dessus et votre Données source partielle.

Consultez La référence et ce tutoriel pour la façon dont cela fonctionne.


2 commentaires

Merci, je sais faire des jointures. Je voulais juste savoir s'il est possible dans SQL de "créer" des données sur la volée à l'aide d'une formule, mais apparemment, cela n'est pas possible. Étrange...


Bien sûr, vous peut utiliser la table factice double pour créer des données à l'aide de formules, mais je ne suis pas convaincu que c'est le moyen le plus simple de résoudre celui-ci.



1
votes

Vous devriez certainement le faire dans votre application plutôt que la couche de DB. Créez simplement un tableau de dates pour la plage de temps et fusionner les données réelles avec les dates vides que vous avez pré-créées. Voir Cette réponse à une question similaire


6 commentaires

Je ne suis pas d'accord ... Je pense qu'il est beaucoup plus propre de le faire en SQL (si possible). J'utilise une grille JavaScript standard qui obtient des données d'un script PHP standard qui exécute la requête et produit des données JSON. Je ne vais pas écrire un script PHP séparé pour récupérer des données pour chaque requête dans ma demande (il y a des centaines de questions dans mon application)


Pourquoi auriez-vous besoin d'écrire un script distinct pour chaque requête?


J'étais exagérant. Je disais juste que je ne pense pas que ce soit propre d'utiliser PHP (ou un autre type de script serverside) pour manipuler les données que vous souhaitez afficher.


Pourtant, vous allez utiliser le langage de script de toute façon pour exécuter la requête, JSON l'encode et émise les résultats. À chacun le sien, mais cela dans la couche DB est aussi inutile que le bâtiment HTML via des requêtes SQL.


Pas inutile du tout. Dans ma solution, je peux utiliser le même script encore et encore pour afficher des données. La seule chose qui est différente chaque fois est la requête de base de données, que je stocke dans des fichiers séparés.


Comme je l'ai dit, à chacun le sien. Rien ne vous empêche de faire ce que vous avez décrit dans votre dernier commentaire lorsque vous utilisez l'approche que j'ai décrite.



0
votes

Je ferais quelque chose comme ceci: xxx

Cela vous donnera le nombre de commandes groupées par chaque mois. Ensuite, dans vous, l'application attribue simplement un zéro au mois auquel aucune donnée n'a été renvoyée

J'espère que cela aide


2 commentaires

Cela ne fonctionne pas quand il n'y a pas de données dans un certain mois. Ce mois ne sera pas affiché alors.


Je sais que c'est pourquoi j'ai dit "Ensuite, l'application affectait simplement un zéro au mois dans lequel aucune donnée n'a été renvoyée". Imo c'est plus propre.



6
votes

Si possible, essayez de rester à l'écart de générer des données à la volée. Il rend des requêtes très simples complexes ridiculées, mais surtout: elle confond l'optimiseur sans fin.

Si vous avez besoin d'une série d'entiers, utilisez une table statique d'entiers. Si vous avez besoin d'une série de dates, de mois ou autre, utilisez une table de calendrier. Sauf si vous avez affaire à des exigences vraiment extraordinaires, une table statique est la voie à suivre.

J'ai donné un exemple sur la façon de créer une table de chiffres et une table de calendrier minimale (seulement des dates) dans Cette réponse .

Si vous avez ces tables en place, il devient facile de résoudre votre requête.

  1. Agrégez les données de la commande au mois.
  2. Joignez-vous à la table des mois (ou du mois distinct de la table des dates)

1 commentaires

Je conviens que ma "solution" est très complexe ... je vais penser que je vais utiliser une table "numéros" ou "calendrier" puis. Bien étrange, bien que SQL après toutes ces années ne soit pas capable de créer une simple série de données.



1
votes

Je fais de la requête suivant pour générer des mois dans un intervalle donné. Pour mon cas, il génère une liste de mois de mai 2013 à partir de mai 2013.

SELECT date_format(@dt:= DATE_ADD( @dt, INTERVAL 1 MONTH),'%M %Y') date_string, 
   @dt as date_full 
FROM (SELECT @dt := DATE_SUB(CAST(DATE_FORMAT('2013-05-01' ,'%Y-%m-01') AS DATE),
   INTERVAL 1 MONTH) ) vars,
   your_tables 
WHERE @dt<NOW()


0 commentaires

1
votes

Si vous utilisez PostgreSQL, vous pouvez combiner à la fois date_trunc et générate_series pour faire quelques Groupement très amusant et génération de séries.

Par exemple, vous pouvez l'utiliser pour générer une table de toutes les dates de l'année dernière: p> xxx pré>

alors, vous pouvez utiliser date_trunc Pour saisir les mois et le groupe par ce champ Date_Rund'ed: P>

SELECT date(date_trunc('month', series.date)) as month, COUNT(*) as days 
FROM (SELECT current_date - s.a as date 
FROM generate_series(0,365,1) as s(a)) series 
GROUP BY month;


0 commentaires

0
votes

Query sur les données statiques MySQL.

Vous pouvez sélectionner des données statiques à partir de la liste des codes papier avec table par cette requête xxx


0 commentaires