SQL合并两个具有不同列号的选择查询,同时删除重复项?

Posted

技术标签:

【中文标题】SQL合并两个具有不同列号的选择查询,同时删除重复项?【英文标题】:SQL Merge Two Select Queries with different column numbers while removing duplicates? 【发布时间】:2018-01-15 07:22:42 【问题描述】:

使用 SQL Server,我有两个带有 Where 子句的 Select 语句,但不断得到重复的结果。我的第一个查询是:

  SELECT
    PricingContingencies.*,
    Terms.*,
    rscDescription  AS RateScheme,
    ptyAbbreviation AS PointTypeAbbreviation,
    FAKs.*,
    fat.*
  FROM ((((PricingContingencies
    INNER JOIN Terms ON pcoTerms = terID)
    INNER JOIN PointTypes ON pcoPointTypeFK = ptyID)
    LEFT JOIN RateSchemes ON pcoRateSchemeFK = rscID)
    LEFT JOIN FAKs ON fakPricingContingencyFK = pcoID)
    LEFT JOIN FuelAgreementTypes fat ON ftyID = pcoFuelAgreementTypeFK
  WHERE pcoPricingAgreementFK = 61523 and pcoID = 16490608

并返回两行(这是正确的)。

我的第二个查询非常相似,但有额外的列(唯一的区别是“LEFT JOIN PalletPricing ON pprPricingContingenciesFK = pcoID)”而不是“LEFT JOIN FAKs ON fakPricingContingencyFK = pcoID)”:

SELECT
  PricingContingencies.*,
  Terms.*,
  rscDescription as RateScheme,
  ptyAbbreviation as PointTypeAbbreviation,
  PalletPricing.*,
  fat.*
FROM ((((PricingContingencies
  INNER JOIN Terms ON pcoTerms = terID)
  INNER JOIN PointTypes ON pcoPointTypeFK = ptyID)
  LEFT JOIN RateSchemes ON pcoRateSchemeFK = rscID)
  LEFT JOIN PalletPricing ON pprPricingContingenciesFK = pcoID)
  LEFT JOIN FuelAgreementTypes fat ON ftyID = pcoFuelAgreementTypeFK
WHERE pcoPricingAgreementFK = 61523 and pcoID = 16490608

并返回6行(这也是正确的)。

如何将它们组合起来,总共得到 8 行?如果我使用 INNER JOIN 将它们组合起来,例如:

SELECT
  FirstSet.*,
  SecondSet.*
FROM (
  SELECT
    PricingContingencies.*,
    Terms.*,
    rscDescription  AS RateScheme,
    ptyAbbreviation AS PointTypeAbbreviation,
    FAKs.*,
    fat.*
  FROM ((((PricingContingencies
    INNER JOIN Terms ON pcoTerms = terID)
    INNER JOIN PointTypes ON pcoPointTypeFK = ptyID)
    LEFT JOIN RateSchemes ON pcoRateSchemeFK = rscID)
    LEFT JOIN FAKs ON fakPricingContingencyFK = pcoID)
    LEFT JOIN FuelAgreementTypes fat ON ftyID = pcoFuelAgreementTypeFK
  WHERE pcoPricingAgreementFK = 61523 and pcoID = 16490608
) as FirstSet
INNER JOIN
  (
    SELECT
      PricingContingencies.*,
      Terms.*,
      rscDescription as RateScheme,
      ptyAbbreviation as PointTypeAbbreviation,
      PalletPricing.*,
      fat.*
    FROM ((((PricingContingencies
      INNER JOIN Terms ON pcoTerms = terID)
      INNER JOIN PointTypes ON pcoPointTypeFK = ptyID)
      LEFT JOIN RateSchemes ON pcoRateSchemeFK = rscID)
      LEFT JOIN PalletPricing ON pprPricingContingenciesFK = pcoID)
      LEFT JOIN FuelAgreementTypes fat ON ftyID = pcoFuelAgreementTypeFK
    WHERE pcoPricingAgreementFK = 61523 and pcoID = 16490608
    ) as SecondSet
ON FirstSet.pcoID = SecondSet.pcoID
ORDER BY FirstSet.pcoPriority DESC

我得到 12 行 PalletPricing 列重复且不正确(第二个结果加倍 [6 x 2])。如何将它们组合起来,以便得到正确的 8 行(2 + 6)?

提前致谢。

【问题讨论】:

您基本上是在寻找 UNION 查询。但是,UNION(或其更具包容性的兄弟,UNION ALL)要求两个查询具有完全相同的列数,并且每列中的数据类型大致相同。除非 PalletPricing 和 Faks 具有相同的表布局,否则有时您将不得不返回假数据,并且来自两个来源中的每一个的列名将设置为您从***查询中输出的任何列名。 它们真的是重复的吗?可能至少有一列不同。 你是对的,一栏是不同的。如何排除那个不同的列,使整行不包含在查询中? 【参考方案1】:

对于你想要的 INNER JOIN 将不起作用。使用像当前代码这样的连接会将每个查询中的所有列塞进非常宽的行中。您需要UNION(不是UNION ALL,因为它专门用于检查重复数据)。

正如您收到的评论所提到的,您必须在每个查询中拥有相同数量的字段,并且它们应该包含等效的数据,否则您的字段将根据它们来自哪个查询而具有两种不同类型的数据。

使用UNION 时,明确指定字段也是一个好主意,.* 是一种冒险的做法,因为您认为所有列在相关表中的顺序相同。所以你可以这样做:

SELECT
    rscDescription  AS RateScheme,
    ptyAbbreviation AS PointTypeAbbreviation,
    FROM ((((PricingContingencies
    INNER JOIN Terms ON pcoTerms = terID)
    INNER JOIN PointTypes ON pcoPointTypeFK = ptyID)
    LEFT JOIN RateSchemes ON pcoRateSchemeFK = rscID)
    LEFT JOIN FAKs ON fakPricingContingencyFK = pcoID)
    LEFT JOIN FuelAgreementTypes fat ON ftyID = pcoFuelAgreementTypeFK
  WHERE pcoPricingAgreementFK = 61523 and pcoID = 16490608
UNION
SELECT
      rscDescription as RateScheme,
      ptyAbbreviation as PointTypeAbbreviation,
    FROM ((((PricingContingencies
      INNER JOIN Terms ON pcoTerms = terID)
      INNER JOIN PointTypes ON pcoPointTypeFK = ptyID)
      LEFT JOIN RateSchemes ON pcoRateSchemeFK = rscID)
      LEFT JOIN PalletPricing ON pprPricingContingenciesFK = pcoID)
      LEFT JOIN FuelAgreementTypes fat ON ftyID = pcoFuelAgreementTypeFK
    WHERE pcoPricingAgreementFK = 61523 and pcoID = 16490608

这只是您的两个明显匹配的字段的示例,您必须逐列进行。

【讨论】:

很遗憾,列不匹配。 FAK 表有 6 列,PalletPricing 表有 9 列。我尝试在第一个查询中为额外的 3 列执行 UNION,但结果在 FAK 表的列中有 PalletPricing 数据不正确,因为第一个查询具有这些列标题。【参考方案2】:

您必须使用“联合所有”而不是内部连接。

 SELECT
    PricingContingencies.*,
    Terms.*,
    rscDescription  AS RateScheme,
    ptyAbbreviation AS PointTypeAbbreviation,
    FAKs.*,
    fat.*
  FROM ((((PricingContingencies
    INNER JOIN Terms ON pcoTerms = terID)
    INNER JOIN PointTypes ON pcoPointTypeFK = ptyID)
    LEFT JOIN RateSchemes ON pcoRateSchemeFK = rscID)
    LEFT JOIN FAKs ON fakPricingContingencyFK = pcoID)
    LEFT JOIN FuelAgreementTypes fat ON ftyID = pcoFuelAgreementTypeFK
  WHERE pcoPricingAgreementFK = 61523 and pcoID = 16490608
union all
    SELECT
      PricingContingencies.*,
      Terms.*,
      rscDescription as RateScheme,
      ptyAbbreviation as PointTypeAbbreviation,
      PalletPricing.*,
      fat.*
    FROM ((((PricingContingencies
      INNER JOIN Terms ON pcoTerms = terID)
      INNER JOIN PointTypes ON pcoPointTypeFK = ptyID)
      LEFT JOIN RateSchemes ON pcoRateSchemeFK = rscID)
      LEFT JOIN PalletPricing ON pprPricingContingenciesFK = pcoID)
      LEFT JOIN FuelAgreementTypes fat ON ftyID = pcoFuelAgreementTypeFK
    WHERE pcoPricingAgreementFK = 61523 and pcoID = 16490608

【讨论】:

以上是关于SQL合并两个具有不同列号的选择查询,同时删除重复项?的主要内容,如果未能解决你的问题,请参考以下文章

如何在火花中合并或连接具有不相等列号的数据框

请问sqlserver中的两个表怎么进行关联

找出oracle中具有不同列号的2个表之间的区别

Python合并两个具有不同日期时间的数据框[重复]

SQL求助:对一个字段里重复数据,取出不同数据的前两个

如何合并具有不同 WHERE 子句的两个 SELECT 查询