【问题标题】:SQL query returns result multiple timesSQL查询多次返回结果 [已解决]
【发布时间】:2021-05-26 00:14:56
【问题描述】:

我对 SQL 很陌生,正在尝试在 SQL 中加入一些表。 我正在使用SQLite3Pandas 并具有以下表结构:

    User
      |
Measurement - Environment - meas_device - Device
      |                          | 
    Data                 Unit_of_Measurement

为什么我多次 (4x) 得到以下 SQL 查询的结果?

query = """
SELECT User.name, Measurement.id, Data.set_id, Data.subset_id, Data.data 
FROM Measurement
JOIN Data ON Measurement.id = Data.measurement_id
JOIN User ON Measurement.user_id = user.id
JOIN Environment ON Measurement.Environment_id = Environment.id
JOIN meas_device ON Environment.meas_dev_ids = meas_device.id
JOIN Device ON meas_device.device_id = Device.id
JOIN Unit_of_Measurement ON meas_device.Unit_id = Unit_of_Measurement.id
WHERE User.name = 'nicola'
"""

pd.read_sql_query(query, conn)

我的猜测是我在加入时做错了,但我看不出是什么。 我希望能够将 JOIN 语句保存在适用于每个可能查询的某个地方,这就是为什么连接的表比此查询所需的多。

更新 我认为问题出在环境表中。每当我加入此表时,结果都会成倍增加。由于 Environment 是 meas_devices 的集合,因此有多个具有相同 Environment id 的条目。 (我可以将具有相应 meas_device_id 的 Environment 表保存为列表,但我认为不可能将 Environment 表与 meas_device 表链接。)

id | meas_device_id
1  |      1
1  |      2
1  |      5
2  |      3
2  |      4

到目前为止,我使用 pandas DataFrame.to_sql() 创建了表,因此 id 没有被标记为主键或类似的东西。这可能是我的问题的原因

更新 2 我发现了问题。我不认为这实际上对将来的某人有帮助。但为了完整起见,这里解释一下。这实际上不是如何链接表格的问题,但我忽略了一个关键链接。因为环境具有多个具有相同值的索引,所以它创建了“开放端”,导致结果相乘。我需要在 Environment.subset_id 和 Data.subset_id 之间添加交叉检查。以下查询工作正常:

query = f""" SELECT {SELECT}
          FROM Data
          JOIN Measurement ON Data.measurement_id = Measurement.id
          JOIN User ON Measurement.user_id = User.id
          JOIN Environment ON Measurement.Environment_id = Environment.id
          JOIN meas_device ON Environment.meas_dev_ids = meas_device.id
          JOIN Device ON meas_device.Device_id = Device.id
          JOIN Unit_of_Measurement ON meas_device.Unit_id = Unit_of_Measurement.id
          WHERE {WHERE} AND Environment.subset_id = Data.subset_id
          """

【问题讨论】:

  • 考虑到pd.merge等价于SQL的JOIN,这和this question的情况差不多
  • 您正在连接不需要列的表。可能其中一个会为每个预期结果记录返回一条以上的记录。单独加入MeasurementDataUser 不会满足您的需要吗?
  • 是的,在这种情况下它会。我希望在某个地方保存一个适用于所有可能查询的连接语句。

标签: python sql pandas sqlite


【解决方案1】:

如果您需要过滤在结果中产生额外行的表(当它们连接时),请不要连接它们,而是将它们包含在 WHERE 子句的子查询中。

例如

SELECT User.name, Measurement.id, Data.set_id, Data.subset_id, Data.data
FROM
    Measurement
    JOIN Data ON Measurement.id = Data.measurement_id
    JOIN User ON Measurement.user_id = user.id
WHERE
    Measurement.Environment_id IN (
        SELECT Environment.id
        FROM
            Environment
            JOIN meas_device ON Environment.meas_dev_ids = meas_device.id
            JOIN Device ON meas_device.device_id = Device.id
            JOIN Unit_of_Measurement ON meas_device.Unit_id = Unit_of_Measurement.id
        WHERE Device.name = 'xy'
    )

在这个子查询中,您可以连接许多表而无需生成额外的记录。

如果这不是一个选项,因为您还想从其他表中选择条目,您可以简单地将 DISTINCT 添加到您的原始查询中。

SELECT DISTINCT
    User.name, Measurement.id, Data.set_id, Data.subset_id, Data.data 
FROM
   Measurement
   JOIN Data ON Measurement.id = Data.measurement_id
   JOIN User ON Measurement.user_id = user.id
   JOIN Environment ON Measurement.Environment_id = Environment.id
   JOIN meas_device ON Environment.meas_dev_ids = meas_device.id
   JOIN Device ON meas_device.device_id = Device.id
   JOIN Unit_of_Measurement ON meas_device.Unit_id = Unit_of_Measurement.id
WHERE
   User.name = 'nicola'

【讨论】:

  • 进行了非常小的修改,实际上可以工作,谢谢。我发现最初的问题在于:JOIN Environment ON Measurement.Environment_id = Environment.id 你知道为什么这会增加我的结果吗?
  • 我刚刚意识到这并不能解决我的问题。我也想使用相同的查询从 meas_device、device 和 unit_of_measurement 中选择条目。这不是这样的
  • 如果你也想从其他表中选择条目,那么问题与你发布的不同。
  • 感谢您的帮助 Olivier Jacot-Descombes。你是对的,我发现了错误,它位于我没有意识到必须创建的两个表之间的链接中。
猜你喜欢
  • 2010-11-13
  • 1970-01-01
  • 2012-05-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-05-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多