数据库
首页 > 数据库> > mysql-如何在某些表上用左联接写正确的sql?

mysql-如何在某些表上用左联接写正确的sql?

作者:互联网

美好的一天.

STRUCTURE TABLES AND ERROR WHEN EXECUTE QUERY ON SQLFIDDLE

我有一些SQL查询:

第一个查询:

SELECT 
            n.Type AS Type,
            n.UserIdn AS UserIdn,
            u.Username AS Username,
            n.NewsIdn AS NewsIdn,
            n.Header AS Header,
            n.Text AS Text,
            n.Tags AS Tags,
            n.ImageLink AS ImageLink,
            n.VideoLink AS VideoLink,
            n.DateCreate AS DateCreate
        FROM News n 
        LEFT JOIN Users u ON n.UserIdn = u.UserIdn 

第二查询:

SELECT 
    IFNULL(SUM(Type = 'up'),0) AS Uplikes, 
    IFNULL(SUM(Type = 'down'),0) AS Downlikes,
    (IFNULL(SUM(Type = 'up'),0) - IFNULL(SUM(Type = 'down'),0)) AS SumLikes
FROM JOIN Likes
WHERE NewsIdn=NewsIdn  //only for example- in main sql NewsIdn = value NewsIdn from row table News
ORDER BY UpLikes DESC

和树查询

SELECT 
count(*) as Favorit
Form Favorites
WHERE NewsIdn=NewsIdn  //only for example- in main sql NewsIdn = value NewsIdn from row table News

我想合并两个查询,显示News表中的所有行,以及News表中每个值NewsIdn的Uplikes,DownLikes和Favorit的数量(即Uplikes,DownLikes和Favorit的数量).新闻的每一行),然后按Uplikes Desc进行排序.

告诉我如何制作?

附言:结果,我想要下一个值

TYPE  USERIDN USERNAME NEWSIDN HEADER TEXT                      TAGS     IMAGELINK       VIDEOLINK DATECREATE                      UPLIKES DOWNLIKES SUMLIKES FAVORIT
image 346412  test     260806  test                                      1388152519.jpg            December, 27 2013 08:55:27+0000 2       0          2       2
image 108546  test2    905554  test2  1231231111111111111111111 123. 123 1388153493.jpg            December, 27 2013 09:11:41+0000 1       0          1       0
text  108546  test2    270085  test3                            123 .123                           December, 27 2013 09:13:30+0000 1       0          1       0
image 108546  test2    764955  test4                                     1388192300.jpg            December. 27 2013 19:58:22+0000 0       1         -1       0

解决方法:

首先,您的表具有varchar(30)的所有“ Idn”结构.看起来那些实际上是其他表的ID键,并且应该是整数,以提高索引和连接性能.

其次,这种类型的过程(尤其是基于Web的过程)是使喜欢,不喜欢和收藏夹的值实际上通过直接将这些列作为计数器(例如:新闻表)来对值进行标准化的完美示例.当某人喜欢,不喜欢或将其作为收藏夹时,请立即对其进行标记并加以处理.如果您是第一次执行批量sql-update,那么还会在表上设置触发器以自动处理相应的计数更新.这样,您只需要直接查询表并按需要排序即可,而不必查询加入所有新闻的所有点赞/记录,并查看哪个最好.在新闻表上建立索引将是您最好的选择.

现在,也就是说,使用现有的表构造,您可以通过预聚合查询并将它们作为别名加入sql FROM子句中来进行操作……

SELECT
      N.Type,
      N.UserIdn,
      U.UserName,
      N.NewsIdn,
      N.Header,
      N.Text,
      N.Tags,
      N.ImageLink,
      N.VideoLink,
      N.DateCreate,
      COALESCE( SumL.UpLikes, 0 ) as Uplikes,
      COALESCE( SumL.DownLikes, 0 ) as DownLikes,
      COALESCE( SumL.NetLikes, 0 ) as NetLikes,
      COALESCE( Fav.FavCount, 0 ) as FavCount
   from
      News N
         JOIN Users U
            ON N.UserIdn = U.UserIdn
         LEFT JOIN ( select 
                           L.NewsIdn,
                           SUM( L.Type = 'up' ) as UpLikes,
                           SUM( L.Type = 'down' ) as DownLikes,
                           SUM( ( L.Type = 'up' ) - ( L.Type = 'down' )) as NetLikes
                        from
                           Likes L
                        group by
                           L.NewsIdn ) SumL
            ON N.NewsIdn = SumL.NewsIdn
         LEFT JOIN ( select 
                           F.NewsIdn,
                           COUNT(*) as FavCount
                        from
                           Favorites F
                        group by
                           F.NewsIdn ) Fav
            ON N.NewsIdn = Fav.NewsIdn
   order by
      SumL.UpLikes DESC

再说一次,我不明白为什么您要为新闻表创建一个自动递增的数字ID列,然后为它的另一个值作为NewsIdn作为varchar.我只是想这样做,而您的其他表直接引用News.ID列…为什么有两列代表相同的组件.显然,您正在汇总的每个表(喜欢,收藏夹)都应具有您要加入或汇总的任何此类条件的索引(因此NewsIdn)列,UserIdn等.

最后提醒一下,这种查询总是针对您的“喜欢”,“最喜欢”的整个表运行汇总,并建议在有人选择它们时使用非规范化的列来保存计数.如果您想显示或更新某个特定的人以更改其喜欢/不喜欢/喜欢的状态,则可以随时返回原始表.

您必须研究一下触发器,因为每个数据库都有自己的语法来处理.

对于表结构,这是我的简化版本(从SQLFiddle示例中删除了许多其他列)

CREATE TABLE IF NOT EXISTS `News` (
 id int(11) NOT NULL AUTO_INCREMENT,
 UserID integer NOT NULL,
 ... other fields
 `DateCreate` datetime NOT NULL,
 PRIMARY KEY ( id ),
 KEY ( UserID )  
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=5 ;

如果您想要由特定用户创建的所有新闻活动,则用户ID上的额外键.

CREATE TABLE IF NOT EXISTS `Users` (
  id int(11) NOT NULL AUTO_INCREMENT,
  other fields...
  PRIMARY KEY ( id ),
  KEY ( LastName, Name )
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=5 ;

如果您想按用户名进行搜索,则需要附加键

CREATE TABLE IF NOT EXISTS `Likes` (
 id int(11) NOT NULL AUTO_INCREMENT,
 UserId integer NOT NULL,
 NewsID integer NOT NULL,
 `Type` enum('up','down') NOT NULL,
 `IsFavorite` enum('yes','no') NOT NULL,
 `DateCreate` datetime NOT NULL,
 PRIMARY KEY (`id`),
 KEY ( UserID ),
 KEY ( NewsID, IsFavorite )
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=6 ;

此处用于连接和/或聚合的其他键.我还添加了一个标志列,使其也成为收藏夹.这可以避免使用收藏夹表,因为它们具有LIKES的相同基本内容.因此,某人可以针对给定的新闻喜欢/不喜欢,但也喜欢/不喜欢它,最终用户希望能够快速参考.

现在,如何简化这些表结构以进行查询?每个表都有其自己的“ id”列,但是任何其他表都使用tableNameID(UserID,NewsID,LikesID或其他名称),这就是联接.

select ...
   from 
      News N
         Join Users U
            on N.UserID = U.ID
         Join Likes L
            on N.ID = L.NewsID

在编写查询时,整数列更容易使用,其他人通常更容易识别.这是否更有意义?

标签:join,left-join,sql,mysql
来源: https://codeday.me/bug/20191122/2058046.html