【发布时间】:2022-01-02 00:36:16
【问题描述】:
我在这个db<>fiddle 中有一组样本数据。数据代表一批根据某些标准属于不同井型类别的井。我正在尝试按井所属的类别对井进行分组,然后根据另一组标准计算每个类别中有多少井。
我当前的查询部分有效,但只能正确计算CASE WHEN 子句层次结构中较高的井。这是因为第一个CASE WHEN 有机会将井类别分配给数据集中的所有井。但是,当它遍历每个CASE WHEN 子句时,查询“see's”的井数减少,因为它用完了可以分配类别的井。到最后,几乎所有的井都已经分配了一个类别,从而根本无法进行某些类别计数。
这是我当前的查询,也在上面的 dbfiddle 链接中:
SELECT
dt.WellCategory,
ISNULL(SUM(CASE WHEN dt.LeaseType IN ('F','I','S','P') OR dt.LeaseType NOT IN ('F', 'I', 'S', 'P', 'U') THEN 1 END), 0) AS [Number of Wells], -- Federal + Indian + State + Fee + Multi-Lease
ISNULL(SUM(CASE WHEN dt.LeaseType = 'F' THEN 1 END), 0) AS [Federal], -- Sums up how many wells from the subquery have a leasetype of "Federal"
ISNULL(SUM(CASE WHEN dt.LeaseType = 'I' THEN 1 END), 0) AS [Indian],
ISNULL(SUM(CASE WHEN dt.LeaseType = 'S' THEN 1 END), 0) AS [State],
ISNULL(SUM(CASE WHEN dt.LeaseType = 'P' THEN 1 END), 0) AS [Fee (Private)],
ISNULL(SUM(CASE WHEN dt.LeaseType NOT IN ('F', 'I', 'S', 'P', 'U') THEN 1 END), 0) AS [Multiple Lease Types]
FROM
(
SELECT -- Subquery labels wells according to their wellstatus, welltype, etc.
c.LeaseType,
CASE
WHEN w.WellStatus = 'p' AND w.WellType = 'gw' OR ((w.WellStatus = 'pai' OR w.WellStatus = 'pii') AND (w.WellType = 'gwi' OR w.WellType = 'ggi' OR w.WellType = 'gwd')) THEN 'Producing Gas Wells'
WHEN w.WellStatus = 'p' AND w.WellType = 'ow' OR ((w.WellStatus = 'pai' OR w.WellStatus = 'pii') AND (w.WellType = 'owi' OR w.WellType = 'ogi' OR w.WellType = 'owd')) THEN 'Producing Oil Wells'
WHEN w.WellStatus = 's' AND w.WellType = 'ow' OR ((w.WellStatus = 'sai' OR w.WellStatus = 'sii') AND (w.WellType = 'owi' OR w.WellType = 'ogi' OR w.WellType = 'owd')) THEN 'Shut-In Oil Wells'
WHEN w.WellStatus = 's' AND w.WellType = 'gw' OR ((w.WellStatus = 'sai' OR w.WellStatus = 'sii') AND (w.WellType = 'gwi' or w.WellType = 'ggi' or w.WellType = 'gwd')) THEN 'Shut-In Gas Wells'
WHEN w.WellStatus = 'a' AND w.WellType = 'wi' THEN 'Active Water Injection Wells'
WHEN w.WellStatus = 'a' AND w.WellType = 'gi' THEN 'Active Gas Injection Wells'
WHEN w.WellStatus = 'a' AND w.WellType = 'wd' THEN 'Active Water Disposal Wells'
WHEN w.WellStatus = 'a' AND w.WellType = 'gs' THEN 'Active Gas Storage Wells'
WHEN w.WellStatus = 'a' AND w.WellType = 'ws' THEN 'Active Water Source Wells'
WHEN w.WellStatus = 'a' AND w.WellType = 'tw' THEN 'Active Test Holes'
WHEN w.WellStatus = 'i' AND w.WellType = 'wi' THEN 'Inactive Water Injection Wells'
WHEN w.WellStatus = 'i' AND w.WellType = 'gi' THEN 'Inactive Gas Injection Wells'
WHEN w.WellStatus = 'i' AND w.WellType = 'wd' THEN 'Inactive Water Disposal Wells'
WHEN w.WellStatus = 'i' AND w.WellType = 'gs' THEN 'Inactive Gas Storage Wells'
WHEN w.WellStatus = 'i' AND w.WellType = 'ws' THEN 'Inactive Water Source Wells'
WHEN w.WellStatus = 'i' AND w.WellType = 'tw' THEN 'Inactive Test Holes'
WHEN w.WellStatus = 'ta' THEN 'Temporarily-Abandoned Wells'
WHEN w.WellStatus = 'pa' THEN 'Plugged and Abandoned Wells'
WHEN c.LateralStatus = 'NEW' THEN 'New Permits - Not Yet Approved'
WHEN c.LateralStatus = 'APD' THEN 'Permits Approved - Not Yet Commenced'
WHEN c.LateralStatus = 'DRL' THEN 'Drilling Commenced - Not Yet Completed'
WHEN c.LateralStatus = 'OPS' THEN 'Drilling Operations Suspended'
WHEN w.WellStatus IN ('drl','ops','p','s','ta','pai','pii','sai','sii','a','i') AND w.Operator = 101600 THEN 'Open Orphan Wells (no known operator)'
WHEN w.WellStatus IN ('drl','ops') THEN 'Total Holes Not Yet Completed'
WHEN ((w.WellStatus = 'p' or w.WellStatus = 's') AND w.WellType <> 'LI') OR (w.WellStatus = 'pai' OR w.WellStatus = 'pii' OR w.WellStatus = 'sai' OR w.WellStatus = 'sii') THEN 'Total Wells Capable of Production'
WHEN (w.WellStatus = 'drl' OR w.WellStatus = 'ops' OR ((w.WellStatus = 'p' or w.WellStatus = 's') AND w.WellType <> 'LI') OR w.WellStatus = 'ta' OR w.WellStatus = 'pai' OR w.WellStatus = 'pii' OR w.WellStatus = 'sai' OR w.WellStatus = 'sii' OR w.WellStatus = 'a' OR w.WellStatus = 'i') THEN 'Total Non-Plugged Wells'
WHEN (w.WellStatus = 'drl' or w.WellStatus = 'ops' or ((w.WellStatus = 'p' or w.WellStatus = 's') and w.WellType <> 'LI') or w.WellStatus = 'ta' or w.WellStatus = 'pai' or w.WellStatus = 'pii' or w.WellStatus = 'sai' or w.WellStatus = 'sii' or w.WellStatus = 'a' or w.WellStatus = 'i' or w.WellStatus = 'pa') THEN 'Total Wells Drilled'
END AS WellCategory
FROM HWell w
LEFT JOIN HConstruct c ON c.WellKey = w.PKey
) dt
GROUP BY dt.WellCategory
ORDER BY dt.WellCategory DESC
这是上面的查询产生的表格:
表 #1
| WellCategory | Number of Wells | Federal | Indian | State | Fee (Private) | Multiple Lease Types |
|---|---|---|---|---|---|---|
| Total Wells Capable of Production | 2 | 2 | 0 | 0 | 0 | 0 |
| Temporarily-Abandoned Wells | 1 | 1 | 0 | 0 | 0 | 0 |
| Shut-In Oil Wells | 21 | 10 | 10 | 0 | 1 | 0 |
| Shut-In Gas Wells | 26 | 19 | 2 | 4 | 1 | 0 |
| Producing Oil Wells | 59 | 18 | 25 | 6 | 10 | 0 |
| Producing Gas Wells | 90 | 59 | 1 | 25 | 5 | 0 |
| Plugged and Abandoned Wells | 113 | 60 | 15 | 19 | 19 | 0 |
| Permits Approved - Not Yet Commenced | 14 | 4 | 2 | 2 | 4 | 2 |
| New Permits - Not Yet Approved | 1 | 0 | 1 | 0 | 0 | 0 |
| Inactive Water Injection Wells | 18 | 11 | 5 | 2 | 0 | 0 |
| Drilling Operations Suspended | 4 | 1 | 3 | 0 | 0 | 0 |
| Drilling Commenced - Not Yet Completed | 4 | 1 | 1 | 0 | 2 | 0 |
| Active Water Injection Wells | 6 | 1 | 5 | 0 | 0 | 0 |
| Active Water Disposal Wells | 1 | 0 | 0 | 1 | 0 | 0 |
| NULL | 140 | 83 | 28 | 14 | 15 | 0 |
这是我知道的同一数据集可以生成的表以及我要复制的表:
表 #2
| Well Statuses | Number Of Wells | Federal | Indian | State | Fee (Private) | Multiple Lease Types |
|---|---|---|---|---|---|---|
| Producing Oil Wells | 59 | 18 | 25 | 6 | 10 | 0 |
| Producing Gas Wells | 90 | 59 | 1 | 25 | 5 | 0 |
| Shut-In Oil Wells | 21 | 10 | 10 | 0 | 1 | 0 |
| Shut-In Gas Wells | 26 | 19 | 2 | 4 | 1 | 0 |
| Active Water Injection Wells | 6 | 1 | 5 | 0 | 0 | 0 |
| Active Gas Injection Wells | 0 | 0 | 0 | 0 | 0 | 0 |
| Active Water Disposal Wells | 1 | 0 | 0 | 1 | 0 | 0 |
| Active Gas Storage Wells | 0 | 0 | 0 | 0 | 0 | 0 |
| Active Water Source Wells | 0 | 0 | 0 | 0 | 0 | 0 |
| Active Test Holes | 0 | 0 | 0 | 0 | 0 | 0 |
| Inactive Water Injection Wells | 18 | 11 | 5 | 2 | 0 | 0 |
| Inactive Gas Injection Wells | 0 | 0 | 0 | 0 | 0 | 0 |
| Inactive Water Disposal Wells | 0 | 0 | 0 | 0 | 0 | 0 |
| Inactive Gas Storage Wells | 0 | 0 | 0 | 0 | 0 | 0 |
| Inactive Water Source Wells | 0 | 0 | 0 | 0 | 0 | 0 |
| Inactive Test Holes | 0 | 0 | 0 | 0 | 0 | 0 |
| Temporarily-Abandoned Wells | 1 | 1 | 0 | 0 | 0 | 0 |
| Plugged and Abandoned Wells | 113 | 60 | 15 | 19 | 19 | 0 |
| New Permits - Not Yet Approved | 1 | 0 | 1 | 0 | 0 | 0 |
| Permits Approved - Not Yet Commenced | 14 | 4 | 2 | 2 | 4 | 2 |
| Drilling Commenced - Not Yet Completed | 4 | 1 | 1 | 0 | 2 | 0 |
| Drilling Operations Suspended | 4 | 1 | 3 | 0 | 0 | 0 |
| Open Orphan Wells (no known operator) | 1 | 1 | 0 | 0 | 0 | 0 |
| Total Holes Not Yet Completed | 8 | 2 | 4 | 0 | 2 | 0 |
| Total Wells Capable of Production | 198 | 108 | 38 | 35 | 17 | 0 |
| Total Non-Plugged Wells | 232 | 123 | 52 | 38 | 19 | 0 |
| Total Wells Drilled | 345 | 183 | 67 | 57 | 38 | 0 |
表 #2 是使用更长的查询生成的,该查询使用多个子查询和临时表来使用它们的DISTINCT w.WellID 计算属于每个类别的井数。此外,完整的数据集有更多的条目,通常每个类别都至少有一些井,而不是那么多的“0”。
我不知道如何告诉查询多次计算井,如果它们属于多个井类别,而不会使查询超长并开始引入临时表,我不希望这样做。 *注意我不想为同一类别计算两次,每个类别只计算一次。
【问题讨论】:
-
你可能说过,我错过了。但是,一口井有可能存在于多个类别中吗?
-
@ChadBaldwin 是的,一口井可以同时出现在多个类别中,但只能计算一次/类别。
-
啊,好吧,这就解释了这个问题。您需要计算多个井可能存在的类别,但 CASE 语句将只返回第一个命中的类别。因此,您需要一个能够按类别生成重复项的解决方案。我会看看我能想出什么。
-
@ChadBaldwin 我想是这样......一口井可以满足几个 CASE 语句的标准。但是,在我的查询中,一旦满足第一个 case 语句,就会分配井类别并且不能将其分配给另一个类别。一旦到最后一个 CASE 语句,就几乎没有任何井可以分配了。
-
是的,我想我明白了。因此,如果您有 1 口井,即“生产气井”和“已批准的许可证”,那么您希望将其计入这两个类别。但由于 CASE 语句的工作方式……它只会计入“生产气井”
标签: sql sql-server count sql-server-2012 subquery