【问题标题】:SQL: JOIN multiple tables with different sizeSQL:连接多个不同大小的表
【发布时间】:2016-08-31 18:14:53
【问题描述】:

我不是经常使用数据库的人,所以答案很简单,但我找不到。 这是我的数据库的简化版本(在 SQLITE 中):

我的数据库中有以下值(我只把 id 放在这里,因为只有它们是相关的):

  • device.id: 1, 2, 3
  • capability.id: 10, 20, 30, 40, 50
  • action.id:100、200、300、400、500
  • action.id_capability: 10, 30, 40, 10, 50

这里是 map_device_cap 中的条目:

  • 1、10
  • 1, 30
  • 1, 40
  • 2、10
  • 2, 20
  • 2, 50
  • 3、20

map_device_action 中的条目:

  • 1, 100
  • 1, 200
  • 1, 300
  • 2, 400
  • 2, 500

现在我想创建分组表 map_device_cap 和 map_device_action 的 SELECT 请求。在这种情况下,结果将是:

  • 1、10、100
  • 1、30、200
  • 1、40、300
  • 2、10、400
  • 2、20、空
  • 2、50、500
  • 3、20、空

注意:表 map_device_cap 将始终大于 map_device_action。

我首先尝试了以下请求:

SELECT map_device_cap.id_device, map_device_cap.id_capability,
       map_device_action.id_action 
FROM map_device_cap NATURAL LEFT JOIN map_device_action

但是这个请求给了我以下结果:

  • 1、10、100
  • 1、10、200
  • 1、10、300
  • 1、30、100
  • 1、30、200
  • 1、30、300
  • 1、40、100
  • 1、40、200
  • 1、40、300
  • 2、10、400
  • 2、10、500
  • 2、20、400
  • 2、20、500
  • 2、50、400
  • 2、50、500
  • 3、20、空

如您所见,有重复的条目,我不知道如何删除它们。

如果有人有想法或需要更多信息,请告诉我。

问候

【问题讨论】:

  • 请同时提供“Action”表中的数据。
  • 我提供它们只是为了提醒:action.id: 100, 200, 300, 400, 500 action.id_capability: 10, 30, 40, 10, 50

标签: sql join sqlite


【解决方案1】:

试试这个

SELECT mdc.id_device,
       mdc.id_capability,
       (SELECT (mda.id_action) 
         FROM action a 
         JOIN map_device_action mda 
              ON a.id_capability = mdc.id_capability 
              AND a.id = mda.id_action
              AND mda.id_device = mdc.id_device
        ) as a
FROM map_device_cap mdc
ORDER BY mdc.id_device,  mdc.id_capability;

【讨论】:

    【解决方案2】:

    一种方法是这样的

    SELECT c.id_device,
           c.id_capability,
           a.id
    FROM #map_device_cap c
         JOIN #action a ON c.id_capability = a.id_capability
         JOIN #map_device_action ma ON a.id = ma.id_action
                                       AND c.id_device = ma.id_device
    UNION
    SELECT c.id_device,
           c.id_capability,
           NULL
    FROM #map_device_cap c
         LEFT JOIN #map_device_action ma ON c.id_device = ma.id_device
    WHERE ma.id_device IS NULL;
    

    我用于测试的完整脚本:

    IF OBJECT_ID('tempdb..#map_device_cap') IS NOT NULL
        DROP TABLE #map_device_cap;
    
    CREATE TABLE #map_device_cap
    (id_device INT,
     id_capability       INT
    );
    
    INSERT INTO #map_device_cap
    VALUES
    (1,
     10
    );
    
    INSERT INTO #map_device_cap
    VALUES
    (1,
     30
    );
    
    INSERT INTO #map_device_cap
    VALUES
    (1,
     40
    );
    INSERT INTO #map_device_cap
    VALUES
    (2,
     10
    );
    INSERT INTO #map_device_cap
    VALUES
    (2,
     50
    );
    INSERT INTO #map_device_cap
    VALUES
    (3,
     20
    );
    
    select * from #map_device_cap
    
    IF OBJECT_ID('tempdb..#map_device_action') IS NOT NULL
        DROP TABLE #map_device_action;
    
    CREATE TABLE #map_device_action(id_device INT,
     id_action       INT);
    
    INSERT INTO #map_device_action
    VALUES
    (1,
     100
    );
    
    INSERT INTO #map_device_action
    VALUES
    (1,
     200
    );
    
    INSERT INTO #map_device_action
    VALUES
    (1,
     300
    );
    
    INSERT INTO #map_device_action
    VALUES
    (2,
     400
    );
    
    INSERT INTO #map_device_action
    VALUES
    (2,
     500
    );
    
    
    select * from #map_device_action
    
    
    IF OBJECT_ID('tempdb..#action') IS NOT NULL
        DROP TABLE #action;
    
    CREATE TABLE #action(id INT,
     id_capability       INT);
    
    INSERT INTO #action
    VALUES
    (100,
     10
    );
    
    INSERT INTO #action
    VALUES
    (200,
     30
    );
    
    INSERT INTO #action
    VALUES
    (300,
     40
    );
    
    INSERT INTO #action
    VALUES
    (400,
     10
    );
    
    INSERT INTO #action
    VALUES
    (500,
     50
    );
    
    
    SELECT c.id_device,
           c.id_capability,
           a.id
    FROM #map_device_cap c
         JOIN #action a ON c.id_capability = a.id_capability
         JOIN #map_device_action ma ON a.id = ma.id_action
                                       AND c.id_device = ma.id_device
    UNION
    SELECT c.id_device,
           c.id_capability,
           NULL
    FROM #map_device_cap c
         LEFT JOIN #map_device_action ma ON c.id_device = ma.id_device
    WHERE ma.id_device IS NULL;
    

    更新了查询以满足您的需求:

    SELECT c.id_device,
           c.id_capability,
           a.id
    FROM map_device_cap c
          JOIN action a ON c.id_capability = a.id_capability
          JOIN map_device_action ma ON a.id = ma.id_action
                                       AND c.id_device = ma.id_device
    UNION
    SELECT c.id_device,
           c.id_capability,
           NULL
    FROM map_device_cap c
         LEFT JOIN map_device_action ma ON c.id_device = ma.id_device
    WHERE ma.id_device IS NULL
    UNION
    SELECT c.id_device,
           c.id_capability,
           NULL
    FROM map_device_cap c
         LEFT JOIN action a ON c.id_capability = a.id_capability
    WHERE a.id_capability IS NULL;
    

    【讨论】:

    • 当设备拥有 2 个功能但只有 1 个操作时,此解决方案不起作用(map_device_cap for device.id = x 返回 2 个条目,但 map_device_action for device.id = x 返回 1 个条目)。感谢您的帮助。这几乎是完美的
    • 我只是更新了我的例子,然后你可以很容易地看到它自己
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-09-22
    • 2019-08-04
    • 1970-01-01
    • 2021-06-07
    • 1970-01-01
    • 2013-05-11
    • 2016-02-23
    相关资源
    最近更新 更多