SQL 从 table 1 中查找不在 table 2 中或在 table 2 中的符合条件的记录
SQL find records from table 1 that are not in table 2 OR in table 2 with condition
我看到很多关于如何查找不在另一个 table 中的记录的示例,但是我在查找不在 table 2 中或者是在 table 两个中,但 freq 列值小于 10%。
我首先要加入一个变体列表,其中包含 BRCA1、BRCA2 和任何以 BRC 开头的基因的整体基因名称,其中变体位于起始位置和终止位置之间。
根据这些结果,我想检查鱼子酱等位基因频率 (k) 和 return 结果,这些结果要么在鱼子酱 table 中没有条目,要么结果在鱼子酱中table,alle_freq < .10。第一次连接的结果需要通过 chr、pos、ref 和 alt 与 kaviar 匹配。
我试过:
SELECT DISTINCT *
FROM puzz p, ensembl ens, kaviar k
WHERE (ens.gene_name IN ('BRCA1', 'BRCA2')
OR ens.gene_name LIKE 'RAS%')
AND p.chr = ens.chromosome
AND p.pos >= ens.start AND p.pos <= ens.stop
AND NOT EXISTS
(SELECT k.chromosome, k.pos, k.ref, k.alt, k.alle_freq, k.alle_cnt
FROM public_hg19.kaviar k
WHERE p.chr = k.chromosome
AND p.pos = k.pos
AND p.ref = k.ref
AND p.alt = k.alt
)
AND p.pos = k.pos
AND p.ref = k.ref
AND p.alt = k.alt
AND k.alle_freq < .10
我也试过:
WITH puzz AS (
SELECT *
FROM puzz p
WHERE p.gt IS NOT NULL
)
SELECT DISTINCT t1.*, kav.*
FROM
(SELECT puzz.*, ens.*
FROM puzz, public_hg19.ensembl_genes AS ens
WHERE (ens.gene_name IN IN ('BRCA1', 'BRCA2')
OR ens.gene_name LIKE 'RAS%')
AND puzz.chr = ens.chromosome
AND puzz.pos BETWEEN ens.start AND ens.stop
AND ens.chromosome NOT LIKE "H%") t1
LEFT JOIN
public_hg19.kaviar as kav
ON kav.chromosome = t1.chr
AND kav.pos = t1.pos
AND kav.ref = t1.ref
AND kav.alt = t1.alt
AND (kav.alle_freq < .10 OR kav.alle_freq IS NULL)
解决方案:
感谢@John Bollinger 提供解决方案的框架。
因为 Impala 没有索引,最快的解决方案涉及创建一个临时 table 来缩小传递给字符串操作的行数,如 ens temp table 所示.
WITH ens AS (
SELECT DISTINCT chromosome as chr, start, stop, gene_name
FROM public_hg19.ensembl_genes
WHERE (gene_name IN ( 'BRCA1', 'BRCA2')
OR gene_name LIKE 'RAS%')
AND chromosome NOT LIKE "H%"
)
SELECT p.*, k.chromosome, k.pos, k.id, k.ref, k.alt,
k.qual, (k.alle_freq * 100) as kav_freqPct, k.alle_cnt as kav_count
FROM
(SELECT DISTINCT p.sample_id, p.chr, p.pos, p.id,
p.ref, p.alt, p.qual, p.filter,
ens.gene_name
FROM ens, p7_ptb.itmi_102_puzzle p
WHERE p.chr = ens.chr
AND p.gt IS NOT NULL
AND p.pos >= ens.start AND p.pos <= ens.stop
) AS p
LEFT JOIN public_hg19.kaviar k
ON p.chr = k.chromosome
AND p.pos = k.pos
AND p.ref = k.ref
AND p.alt = k.alt
WHERE COALESCE(k.alle_freq, 0.0) < .10
正如@Gordon Linoff 所指出的,下一行也可能是
WHERE (k.alle_freq IS NULL OR k.alle_freq < 0.10)
两个最终子句 return 的结果相同,但在 impala 上,合并函数不知何故更快。
您提出的两个查询似乎不匹配。 Table 名称不同,并且某些过滤条件根本不相关。特别是,条件 AND ens.chromosome NOT LIKE "H%"
(引号不正确)从何而来?
我确实认为您的外连接方法很有前途,但我不明白您为什么需要 CTE 或内联视图。
此外,"any gene that starts with 'BRC'" 包括 'BRCA1' 和 'BRCA2',因此您无需单独测试它们。删除冗余条件可能会稍微提高性能。
此外,如果您的数据结构恰好会排除重复行,那么明确选择 DISTINCT
行对您没有帮助,反而可能会伤害您。 (尽管如此,我还是遵循您的建议,将其包含在我建议的查询中。)如果有很多结果,那么 SELECT DISTINCT
是昂贵的;特别是如果您选择了很多列。
这似乎准确地表达了您描述的查询:
SELECT DISTINCT
p.sample_id, p.chr, p.pos, p.ref,
p.alt, p.gt, p.qual, p.filter
FROM
p7_ptb.itmi_102_puzzle p
join public_hg19.ensembl_genes ens
ON p.chr = ens.chromosome
left join public_hg19.kaviar k
ON p.chr = k.chromosome
AND p.pos = k.pos
AND p.ref = k.ref
AND p.alt = k.alt
WHERE
ens.gene_name LIKE 'BRC%'
AND ens.chromosome NOT LIKE 'H%'
AND p.pos BETWEEN ens.start AND ens.stop
AND COALESCE(k.alle_freq, 0.0) < .10
如果它对您来说不够快,那么您需要检查您的查询计划以确定瓶颈是什么,而不是试图猜测。
你能做到吗?
select * from `mytables`
where not exists
(select * from `kaviar`)
or in (select * from `kaviar` where alle_freq < .1)
SELECT t1.*
FROM table1 t1
LEFT JOIN table2 t2
ON t1.col1 = t2.col1
WHERE t2.col1 IS NULL
OR t2.alle_freq < 10
首先修复您的基本查询以使用正确的 join
语法并简化逻辑(例如,IN
是不必要的)。
SELECT DISTINCT *
FROM puzz p JOIN
ensembl ens
ON p.chr = ens.chromosome AND
p.pos >= ens.start AND p.pos <= ens.stop
WHERE ens.gene_name LIKE 'BRC%'
我怀疑不需要 DISTINCT
。如果不是,请将其删除。然后,根据需要使用 LEFT JOIN
和其他逻辑:
SELECT DISTINCT *
FROM puzz p JOIN
ensembl ens
ON p.chr = ens.chromosome AND
p.pos >= ens.start AND p.pos <= ens.stop LEFT JOIN
kaviar k
ON p.chr = k.chromosome AND
p.pos = k.pos AND
p.ref = k.ref AND
p.alt = k.alt
WHERE ens.gene_name LIKE 'BRC%' AND
(k.chr IS NULL OR k.alle_freq < 0.10)
注意:这是您使用 left join
的情况,但第二个 table 的条件进入 WHERE
子句而不是 ON
子句。
我看到很多关于如何查找不在另一个 table 中的记录的示例,但是我在查找不在 table 2 中或者是在 table 两个中,但 freq 列值小于 10%。
我首先要加入一个变体列表,其中包含 BRCA1、BRCA2 和任何以 BRC 开头的基因的整体基因名称,其中变体位于起始位置和终止位置之间。
根据这些结果,我想检查鱼子酱等位基因频率 (k) 和 return 结果,这些结果要么在鱼子酱 table 中没有条目,要么结果在鱼子酱中table,alle_freq < .10。第一次连接的结果需要通过 chr、pos、ref 和 alt 与 kaviar 匹配。
我试过:
SELECT DISTINCT *
FROM puzz p, ensembl ens, kaviar k
WHERE (ens.gene_name IN ('BRCA1', 'BRCA2')
OR ens.gene_name LIKE 'RAS%')
AND p.chr = ens.chromosome
AND p.pos >= ens.start AND p.pos <= ens.stop
AND NOT EXISTS
(SELECT k.chromosome, k.pos, k.ref, k.alt, k.alle_freq, k.alle_cnt
FROM public_hg19.kaviar k
WHERE p.chr = k.chromosome
AND p.pos = k.pos
AND p.ref = k.ref
AND p.alt = k.alt
)
AND p.pos = k.pos
AND p.ref = k.ref
AND p.alt = k.alt
AND k.alle_freq < .10
我也试过:
WITH puzz AS (
SELECT *
FROM puzz p
WHERE p.gt IS NOT NULL
)
SELECT DISTINCT t1.*, kav.*
FROM
(SELECT puzz.*, ens.*
FROM puzz, public_hg19.ensembl_genes AS ens
WHERE (ens.gene_name IN IN ('BRCA1', 'BRCA2')
OR ens.gene_name LIKE 'RAS%')
AND puzz.chr = ens.chromosome
AND puzz.pos BETWEEN ens.start AND ens.stop
AND ens.chromosome NOT LIKE "H%") t1
LEFT JOIN
public_hg19.kaviar as kav
ON kav.chromosome = t1.chr
AND kav.pos = t1.pos
AND kav.ref = t1.ref
AND kav.alt = t1.alt
AND (kav.alle_freq < .10 OR kav.alle_freq IS NULL)
解决方案: 感谢@John Bollinger 提供解决方案的框架。
因为 Impala 没有索引,最快的解决方案涉及创建一个临时 table 来缩小传递给字符串操作的行数,如 ens temp table 所示.
WITH ens AS (
SELECT DISTINCT chromosome as chr, start, stop, gene_name
FROM public_hg19.ensembl_genes
WHERE (gene_name IN ( 'BRCA1', 'BRCA2')
OR gene_name LIKE 'RAS%')
AND chromosome NOT LIKE "H%"
)
SELECT p.*, k.chromosome, k.pos, k.id, k.ref, k.alt,
k.qual, (k.alle_freq * 100) as kav_freqPct, k.alle_cnt as kav_count
FROM
(SELECT DISTINCT p.sample_id, p.chr, p.pos, p.id,
p.ref, p.alt, p.qual, p.filter,
ens.gene_name
FROM ens, p7_ptb.itmi_102_puzzle p
WHERE p.chr = ens.chr
AND p.gt IS NOT NULL
AND p.pos >= ens.start AND p.pos <= ens.stop
) AS p
LEFT JOIN public_hg19.kaviar k
ON p.chr = k.chromosome
AND p.pos = k.pos
AND p.ref = k.ref
AND p.alt = k.alt
WHERE COALESCE(k.alle_freq, 0.0) < .10
正如@Gordon Linoff 所指出的,下一行也可能是
WHERE (k.alle_freq IS NULL OR k.alle_freq < 0.10)
两个最终子句 return 的结果相同,但在 impala 上,合并函数不知何故更快。
您提出的两个查询似乎不匹配。 Table 名称不同,并且某些过滤条件根本不相关。特别是,条件 AND ens.chromosome NOT LIKE "H%"
(引号不正确)从何而来?
我确实认为您的外连接方法很有前途,但我不明白您为什么需要 CTE 或内联视图。
此外,"any gene that starts with 'BRC'" 包括 'BRCA1' 和 'BRCA2',因此您无需单独测试它们。删除冗余条件可能会稍微提高性能。
此外,如果您的数据结构恰好会排除重复行,那么明确选择 DISTINCT
行对您没有帮助,反而可能会伤害您。 (尽管如此,我还是遵循您的建议,将其包含在我建议的查询中。)如果有很多结果,那么 SELECT DISTINCT
是昂贵的;特别是如果您选择了很多列。
这似乎准确地表达了您描述的查询:
SELECT DISTINCT
p.sample_id, p.chr, p.pos, p.ref,
p.alt, p.gt, p.qual, p.filter
FROM
p7_ptb.itmi_102_puzzle p
join public_hg19.ensembl_genes ens
ON p.chr = ens.chromosome
left join public_hg19.kaviar k
ON p.chr = k.chromosome
AND p.pos = k.pos
AND p.ref = k.ref
AND p.alt = k.alt
WHERE
ens.gene_name LIKE 'BRC%'
AND ens.chromosome NOT LIKE 'H%'
AND p.pos BETWEEN ens.start AND ens.stop
AND COALESCE(k.alle_freq, 0.0) < .10
如果它对您来说不够快,那么您需要检查您的查询计划以确定瓶颈是什么,而不是试图猜测。
你能做到吗?
select * from `mytables`
where not exists
(select * from `kaviar`)
or in (select * from `kaviar` where alle_freq < .1)
SELECT t1.*
FROM table1 t1
LEFT JOIN table2 t2
ON t1.col1 = t2.col1
WHERE t2.col1 IS NULL
OR t2.alle_freq < 10
首先修复您的基本查询以使用正确的 join
语法并简化逻辑(例如,IN
是不必要的)。
SELECT DISTINCT *
FROM puzz p JOIN
ensembl ens
ON p.chr = ens.chromosome AND
p.pos >= ens.start AND p.pos <= ens.stop
WHERE ens.gene_name LIKE 'BRC%'
我怀疑不需要 DISTINCT
。如果不是,请将其删除。然后,根据需要使用 LEFT JOIN
和其他逻辑:
SELECT DISTINCT *
FROM puzz p JOIN
ensembl ens
ON p.chr = ens.chromosome AND
p.pos >= ens.start AND p.pos <= ens.stop LEFT JOIN
kaviar k
ON p.chr = k.chromosome AND
p.pos = k.pos AND
p.ref = k.ref AND
p.alt = k.alt
WHERE ens.gene_name LIKE 'BRC%' AND
(k.chr IS NULL OR k.alle_freq < 0.10)
注意:这是您使用 left join
的情况,但第二个 table 的条件进入 WHERE
子句而不是 ON
子句。