按具有JOIN,LEFT JOIN和UNION的子查询排序

时间:2018-11-23 10:47:24

标签: sql join subquery left-join union

我的问题是:我如何通过PositionAssetId排序子查询,然后根据表TrxAssetPool跟随其相关的PhysicalAssetId?

我需要LEFT JOIN,因为并非所有的Position和Physical都链接在一起。一些职位/实际职位是独立的。物理可能存在于PhysicalAsset和TrxPhysicalAsset中,但由于未链接到任何位置而在TrxAssetPool中不存在。反之亦然。这些数据也需要显示。

CREATE TABLE `PositionAssets` (
  `Id` int(5) unsigned NOT NULL,
  `Code` varchar(50) NOT NULL,
  `Desc` varchar(200) NOT NULL,
  PRIMARY KEY (`Id`)
);
CREATE TABLE `PhysicalAssets` (
  `Id` int(5) unsigned NOT NULL,
  `Code` varchar(50) NOT NULL,
  `Desc` varchar(200) NOT NULL,
  PRIMARY KEY (`Id`)
);
CREATE TABLE `TrxPositionAssets` (
  `Id` int(5) unsigned NOT NULL,
  `MaintTrxId` int(5) unsigned NOT NULL,
  `PositionAssetId` int(5) NOT NULL,
  PRIMARY KEY (`Id`,`MaintTrxId`)
);
CREATE TABLE `TrxPhysicalAssets` (
  `Id` int(5) unsigned NOT NULL,
  `MaintTrxId` int(5) unsigned NOT NULL,
  `PhysicalAssetId` int(5) NOT NULL,
  PRIMARY KEY (`Id`,`MaintTrxId`)
);
CREATE TABLE `TrxAssetPool` (
  `Id` int(5) unsigned NOT NULL,
  `MaintTrxId` int(5) NOT NULL,
  `PositionAssetId` int(5) NOT NULL,
  `PhysicalAssetId` int(5) NOT NULL,
  PRIMARY KEY (`Id`)
);
INSERT INTO `PositionAssets` (`Id`, `Code`, `Desc`) VALUES
  ('1', 'PositionC', 'Air conditioner'),
  ('2', 'PositionB', 'Laptop'),
  ('3', 'PositionA', 'Mobile Phone')
  ;
INSERT INTO `PhysicalAssets` (`Id`, `Code`, `Desc`) VALUES
  ('1', 'PhysicalD', 'Dunlop Car Tyre'),
  ('2', 'PhysicalA1', 'Samsung'),
  ('3', 'PhysicalB2', 'Acer'),
  ('4', 'PhysicalB1', 'Lenovo')
  ;
INSERT INTO `TrxPositionAssets` (`Id`, `MaintTrxId`, `PositionAssetId`) VALUES
  ('1', '1', '2'),
  ('2', '1', '3'),
  ('3', '1', '1')
  ;
INSERT INTO `TrxPhysicalAssets` (`Id`, `MaintTrxId`, `PhysicalAssetId`) VALUES
  ('1', '1', '2'),
  ('2', '1', '3'),
  ('3', '1', '1'),
  ('4', '1', '4')
  ;
INSERT INTO `TrxAssetPool` (`Id`,`MaintTrxId`,`PositionAssetId`,`PhysicalAssetId`) VALUES
  ('1', '1', '3', '2'),
  ('2', '1', '2', '4'),
  ('3', '1', '2', '3')
  ; 

SELECT DataType, DataCode, DataDesc 
FROM ( 
    SELECT 'Position' AS DataType, pos.Code AS DataCode, pos.Desc AS DataDesc
        FROM TrxPositionAssets trxpos
        JOIN PositionAssets pos ON pos.Id = trxpos.PositionAssetId
        LEFT JOIN TrxAssetPool trxpool ON (trxpool.PositionAssetId = trxpos.PositionAssetId and trxpool.MaintTrxId = trxpos.MaintTrxId)
        WHERE trxpos.MaintTrxId = 1
    UNION
    SELECT 'Physical' AS DataType, phy.Code AS DataCode, phy.Desc  AS DataDesc
        FROM TrxPhysicalAssets trxphy
        JOIN PhysicalAssets phy ON phy.Id = trxphy.PhysicalAssetId
        LEFT JOIN TrxAssetPool trxpool ON (trxpool.PhysicalAssetId = trxphy.PhysicalAssetId and trxpool.MaintTrxId = trxphy.MaintTrxId)
        WHERE trxphy.MaintTrxId = 1  
) DataPool

Sample at sqlfiddle.com

当前结果:

DataType    DataCode    DataDesc

Position    PositionA   Mobile Phone
Position    PositionB   Laptop
Position    PositionC   Air conditioner
Physical    PhysicalA1  Samsung
Physical    PhysicalB1  Lenovo
Physical    PhysicalB2  Acer
Physical    PhysicalD   Dunlop Car Tyre

预期结果:

DataType    DataCode    DataDesc

Position    PositionA   Mobile Phone
Physical    PhysicalA1  Samsung
Position    PositionB   Laptop
Physical    PhysicalB1  Lenovo
Physical    PhysicalB2  Acer
Position    PositionC   Air conditioner
Physical    PhysicalD   Dunlop Car Tyre

空调与任何物理无关。 Dunlop汽车轮胎与任何职位都没有关系。

3 个答案:

答案 0 :(得分:1)

在查询末尾,

ORDER BY DATA.DataId ASC;

答案 1 :(得分:1)

您需要在子查询中选择所需的信息。另外,LEFT JOIN不是必需的,因为WHERE撤消了它们,并且您可能想要UNION ALL

SELECT Data.[DataId], Data.[TrxnDataId], Data.[Type]
FROM ((SELECT pa.[Id] AS DataId, tpa.[Id] AS TrxnDataId, 'Position' AS Type,
              tap.PositionAssetId, 1 as ord
       FROM {TrxPositionAssets} tpa JOIN
            {PositionAssets} pa
            ON pa.[Id] = tpa.[PositionAssetId] JOIN
            TrxAssetPool} tap
            ON tap.[PositionAssetId] = pa.[Id] AND tap.[TrxId] = tpa.[TrxId])
         WHERE tpa.[TrxId] = @TrxId 
      ) UNION ALL
      (SELECT pa.[Id] AS DataId, tpa.[Id] AS TrxnDataId, 'Physical' AS Type,
              tap.PositionAssetId, 2 as ord
       FROM {TrxPhysicalAssets} tpa JOIN
            {PhysicalAssets} pa
            ON pa.[Id] = tpa.[PhysicalAssetId] JOIN
            {TrxAssetPool} tap
            ON tap.[PhysicalAssetId] = pa.[Id] AND tap.[TrxId] = tpa.[TrxId]
       WHERE tpa.[TrxId] = @TrxId
      )
     ) data 
ORDER BY PositionAssetId, ord, dataId;

答案 2 :(得分:0)

要解决您的问题,您必须简化并逐步解决,找到解决方案将更加容易。

例如只需加入两个表

SELECT Orders.OrderID, Customers.CustomerName, Orders.OrderDate
FROM Orders
INNER JOIN Customers ON Orders.CustomerID=Customers.CustomerID;