0

user_diary_number を計算するのに役立つ 2 つのビューを作成し、日記番号 > 合計ユーザーの user_diary_number の平均であるユーザーを選択しました。

2 つのビューは次のようになります。

create view user_diary_number as
(
select user_id,count( distinct diary_id ) as diary_num
from user_diary

group by user_id
);

そして 2 番目havingに andを使用avg:

create view hw_diary as
(
select u.user_id, u.realname, ud.diary_num, school.school_name
from (user as u cross join user_diary_number as ud on u.user_id = ud.user_id )cross join school on u.school_id = school.school_id
having diary_num > avg(diary_num)

);

現在の問題は、2 番目のビューには 1 行の結果しかありません。そして絶対に、ダイアリー番号 > 平均 diary_num のユーザーが 1 人以上います。実際、合計 251 個の日記と 103 人のユーザーがいます。一部のユーザーは、9、4、5 の日記を持っています。しかし、結果は 3 つの日記を持っている 1 人のユーザーにのみ表示されます。

私の相対テーブルは次のとおりです。

CREATE TABLE IF NOT EXISTS `school` (
  `school_id` int(11) NOT NULL,
  `school_name` varchar(45) NOT NULL,
  `location` varchar(45) NOT NULL,
  `master` varchar(45) NOT NULL,
  `numbers_of_student` int(11) NOT NULL,
  PRIMARY KEY (`school_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE IF NOT EXISTS `user_diary` (
  `diary_id` int(11) NOT NULL AUTO_INCREMENT,
  `user_id` int(11) NOT NULL,
  `title` varchar(45) NOT NULL,
  `content` varchar(255) NOT NULL,
  `addtime` DATETIME NOT NULL,
  PRIMARY KEY (`diary_id`,`user_id`),
  KEY `fk_diary_user_id_idx` (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;

クロス結合に問題はありますか? または、他の何か?どうもありがとう!

4

3 に答える 3

4

そのように avg を使用することはできません。私の個人的な映画データベースでは、

select * from movie having year > avg(year);

何も生成せず、

select * from movie having year > (select avg (year) from movie);

期待される結果を生成します。

于 2012-12-30T01:33:19.710 に答える
1

別のサブクエリで平均を計算する必要があります。

何かのようなもの:

select ...
from ...
group by ...
having diary_num > (
    select avg(diary_num)
    from ...) 

意味のあるもので空白を埋めることができます

于 2012-12-30T01:37:59.810 に答える
1

このようなものは、探している結果セットを返すはずです:

 SELECT u.user_id
      , u.realname
      , c.diary_num
      , s.school_name
   -- , a.diary_avg
   FROM ( SELECT d.user_id
               , COUNT(DISTINCT d.diary_id) AS diary_num
            FROM user_diary d
        ) c
   JOIN user u
     ON u.user_id = c.user_id
   JOIN school s
     ON s.school_id = u.school_id
   JOIN ( SELECT AVG(v.diary_num) AS diary_avg
            FROM ( SELECT t.user_id
                        , COUNT(DISTINCT t.diary_id) AS diary_num
                     FROM user_diary t
                 ) v
        ) a
     ON a.diary_avg < c.diary_num
  ORDER BY 1

as というエイリアスが付けられたインライン ビューcは、各ユーザーの diary_num (カウント) を取得します。

エイリアスが付けられたインライン ビューaは、すべてのユーザーのすべての diary_num の平均を取得します。これにより、カウントの「平均」が得られます。これは、元のクエリが意図していたように見えます。

別の方法として、ユーザーごとの日記の「平均」数を、すべての日記の合計数をすべてのユーザーの合計数で割ったものとして取得することもできます。これを行うには、エイリアス化されたインライン ビューaを次のように置き換えます。

        ( SELECT COUNT(DISTINCT t.diary_id)
                 / NULLIF(COUNT(DISTINCT v.user_id),0) AS diary_avg
            FROM user v
            LEFT
            JOIN user_diary t
              ON t.user_id = v.user_id
        ) a

これは、計算の平均ではなく、合計数の計算であるため、わずかに異なる結果が得られます。


ノート

このCROSSキーワードは、MySQL オプティマイザには影響しません。

通常、CROSS将来のレビュー担当者向けのドキュメントとしてキーワードを含めます。これは、通常のON節を意図的に省略したことを示しています。(レビュー担当者として、ON 句のない JOIN を見ると、「意図しないデカルト積の可能性」が頭に浮かびます...著者がキーワードを含めることで、句の省略が意図的であっCROSSたことを私たち (レビュー担当者) に警告します。ON

CROSSしかし、MySQL オプティマイザは、キーワードが含まれているか省略されているかを気にしません。


もう 1 つの質問: MySQL は「ビューの SELECT の FROM 句にサブクエリが含まれています」をサポートしていますか?

A:本当に古いバージョン (3.x ?) の MySQL は、サブクエリをサポートしていませんでした。しかし確かに、MySQL 5.1 以降はサブクエリをサポートしています。

あなたの質問に答えるために、はい、SELECT ステートメントを別のクエリの行ソースとしてインライン ビューとして使用できます。

SELECT v.*
  FROM (
         SELECT 1 AS foo
       ) v
于 2012-12-30T01:51:12.623 に答える