【问题标题】:Oracle SQL - Compare Columns - SELECT records for values that do not have a matchOracle SQL - 比较列 - 选择不匹配的值的记录
【发布时间】:2014-10-01 22:18:10
【问题描述】:

背景
我编写的大多数脚本都会搜索缺少数据的记录。我使用 XXXX_APPL_NO (WHERE XXXX_APPL_NO = YYYY_APPL_NO) 中的常用值来确保我选择的数据来自正确的行。
如果此人有多个应用程序,则 APPL_NO 将有多行记录。
如果 XXXX_APPL_NO 不等于 YYYY_APPL_NO(因为缺少数据),脚本将忽略行。所以我不能使用WHERE XXXX_APPL_NO = YYYY_APPL_NO
我必须欺骗它给我我想要的数据。我相信我已经想到了检索它的过程,但我只是不知道如何编码!

这是实际数据。注意:我不知道空白字段中有什么。约束是“NOT NULL”所以我相信那里有东西,我只是不知道它是什么!

这是我当前的代码:

Select distinct 
sp.spriden_id as "ID", 
SP.SPRIDEN_LAST_NAME as "Last", 
SP.SPRIDEN_FIRST_NAME as "First",
SA.SARADAP_TERM_CODE_ENTRY as "App Term",  
SA.SARADAP_ADMT_CODE as "Adm Type",
st.SARAATT_TERM_CODE,
st.SARAATT_APPL_NO,
sa.SARADAP_APPL_NO
/* I want to make a column in my report ONLY - NOT IN THE DATABASE - 
to print out "No WSP" if there is no corresponding SARAATT_APPL_NO 
for the SARADAP_APPL_NO  */

FROM 
SPRIDEN SP
JOIN SARADAP SA
on sp.spriden_pidm = sa.saradap_PIDM
JOIN SORLCUR SR
on sp.spriden_pidm = SR.SORLCUR_PIDM
full outer JOIN SARAATT ST
on sp.spriden_pidm = ST.SARAATT_PIDM

Where 
Sp.spriden_change_ind is null
AND
SA.SARADAP_ADMT_CODE in ('SP', 'XT' )

这是我当前代码返回的数据。请注意 Term_Codes 和 Appl_Nos 不匹配:

请注意:如果我在 WHERE 子句中添加st.SARAATT_APPL_NO = sa.SARADAP_APPL_NO,它将跳过所有缺少数据的行! (我需要所有数据,以便清除不需要的数据)
这是我添加st.SARAATT_APPL_NO = sa.SARADAP_APPL_NO 时返回的数据。

为了检索我需要的数据,我想做这样的事情:
从当前 SELECT 语句中选择所有数据。
然后,对于每个 SARADAP_APPL_NO,在 SARAATT_APPL_NO 中找到它的匹配项。
SELECT 那些没有匹配项的行,并在我为报告创建的列中打印“No WSP”(不在数据库)。
这就是我所说的“它有匹配吗?”:

或者我可以为某个 spriden_id 做某种
SARADAP_APPL_NO not in (SARAATT_APPL_NO) 吗?
3 4 not in (2 3 4 5)
如果任何 SARAATT_AAPL_NO 值 (2 3 4 5) 未包含在 SARADAP_APPL_NO 值 (3 4) 中,它将选择 SARAATT_APPL_NO 的 2 5 行并在我为报告制作的列中打印“No WSP”。

我匹配吗?相比?搜索?

这些是我想要的结果:

我可以做这样的事情并将其添加到代码中的某处吗?我想先选择数据,然后循环通过我选择的内容。

DECLARE
SARADAP_Count number() = 0;
SARAATT_Count number() = 0;

/* to keep going through the SARAATT_APPL_NO column until the end */
WHILE SA.SARADAP_APPL_NO not null 
    LOOP
    /*  If value being looked at in SARADAP = the value being looked at in SARAATT */
    IF SARADAP_APPL_NO = st.SARAATT_APPL_NO  
        /*  Then add 1 to the count so we can compare the next value in SARADAP  with the values in SARAATT*/
        THEN SARADAP_Count = SARADAP_Count + 1 
        /*  Otherwise add 1 to the count to look at the next SARAATT value*/
        ELSE SARAATT_Count = SARAATT_Count + 1; 
        /* when we  have compared all the values in SARAATT for one SARADAP value, and no     values matched, then print 'No WSP' in the "My Report Column" */ 
        WHEN SARADAP_APPL_NO <> st.SARAATT_APPL_NO THEN return 'NO WSP' in "MY REPORT COLUMN" 
        /* Now go to the next SARADAP row to compare that value with the values in SARAATT */ 
            LOOP
            SARADAP_Count = SARADAP_Count +1 /*  */
                END LOOP
    END LOOP 

___________________________________________________________________________________

  1. 我正在使用两个主要表:SARADAP 和 SARAATT。 SARADAP 是实际的入学申请。 SARAATT 包含属性,并与应用程序具有公共字段(SARAATT/SARADAP _PIDM、SARAATT/SARADAP _TERM_CODE 和 SARAATT/SARADAP _APPL_NO)
  2. 第三张表是 SPRIDEN,包含此人的传记信息。我只需要该表中的 ID。
  3. 我的 SELECT 语句包含两个主表的 TERM_CODE 和 APPL_NO 列,但 WHERE 子句不包含使两个表中的 TERM_CODE 或 APPL_NO 匹配的条件。这意味着不是行是一致的(如下图所示),查询只是收集信息并将其放入打印输出中。
  4. 问题:如果我添加一个条件(SARADAP_APPL_NO = st.SARAATT_APPL_NOSARADAP_TERM_CODE = st.SARAATT_TERM_CODE),我真的需要的信息将不会被选中。
  5. 我真正需要的是让查询告诉我 SARAATT_ATTS_CODE 在哪里没有对应于 APPL_NO 或 TERM_CODE 的行。我无法获得该信息,因为 SARAATT_ATTS_CODE 在该行中没有“任何内容”,因此被查询忽略。它有一个 NOT NULL 约束,所以我不能简单地搜索 NULL 值。 (这是我试图通过LOOP 或其他方式解决的真正问题)
  6. 由于查询不会返回我需要的结果(显示未填充 ATTS_CODE 的位置),因此我的工作思路是查看两个 APPL_NO 列并查找不在这两个列中的值。那些将是拥有未填充 SARAATT_ATTS_CODE 行的人。
    这是数据库中的实际 DATA(但我添加了“我的列”只是为了显示我想要打印的内容

这些是我当前查询的结果

toddlermenot,您在 WITH 子句中询问了 Toddlerminot 查询的结果:
我按 SARADAP_APPL_NO 对结果进行了排序。请注意,红色的数据是混淆的。它不是真正应该在的位置,并且缺少 200810 和 201510 术语以及相应的应用程序编号(2 和 5)。这是当查询只是查找该表中存在的任何值(我相信它正在使用下一个可用值)并将其放置在该行中,因为该行中实际上没有任何内容 - 或者查询与 APPPL 不匹配数字和条款。

整个 Toddlerminot 查询的结果 我按 SARADAP_APPL_NO 对结果进行了排序。

我现在将尝试“创建一个小示例,例如在 sqlfiddle 中发布的 [Toddlerminot] 以说明 [我] 面临的问题。我会将其添加到我的问题中。

我在 Fiddle 中做到了。 sqlfiddle.com/#!4/f4d10/2 请注意,我为空白值输入了“”,因为存在非空约束。我认为它实际上是现在http://www.sqlfiddle.com/#!4/aa83f/1,因为我再次对其进行了编辑。我将数据类型更改为 Number(2,0) 并输入 0 而不是 ' '

这就是表格的样子,这是 Maria Smith 每个表格中的数据。

【问题讨论】:

  • 根据您的帖子标题;你可以简单地像select * from your_table where columna not in (select distinct columnb from your_table)
  • @Rahul 感谢您的回复。我不确定你的意思。总共涉及4列。我要比较/匹配/搜索的两列是st.SARAATTsa.SARADAP
  • @Rahul 我添加了SA.SARADAP_APPL_NO not in (SELECT DISTINCT st.SARAATT_APPL_NO FROM SARAATT ST),但没有选择任何行。

标签: sql oracle search compare match


【解决方案1】:

编辑 3: 使用您发布的数据模型,我构建了这个:http://www.sqlfiddle.com/#!4/f1665/10

让我知道这是否适合你。

几件事:

  • SPIDEN 中的所有 4 行都是重复的。所以只保留了一个。
  • 表 SORLCUR 未在任何地方使用,也未在发布的屏幕截图中使用。所以从查询中删除它。
  • 在发布的屏幕截图中找不到引用的几列。所以从查询中删除了他们。
  • 您突出显示的数据差异是由于在联接条件中遗漏了 TERM_CODE 导致的笛卡尔联接造成的。
  • 报告列按预期工作。

您似乎想要一个用于报告的伪列。

如果我正确解析了您的问题,下面应该可以解决问题:

编辑:根据您的评论/编辑,我更新了查询:

编辑 2: 没有整个数据模型仍然很难说,但如果我理解正确的话,有两个问题:

1 - 数据以红色突出显示:我的猜测 -> 这是因为使用了 FULL OUTER JOIN 而不是 LEFT OUTER JOIN。更新在下面的代码中。试着告诉我。

2 - “我的报告列”显示为空白:不知道为什么这不起作用,您的 SQL 小提琴似乎表明它有效。

WITH t AS
(
    SELECT DISTINCT 
            SP.SPRIDEN_ID AS "ID", 
            SP.SPRIDEN_LAST_NAME AS "LAST", 
            SP.SPRIDEN_FIRST_NAME AS "FIRST",
            SA.SARADAP_TERM_CODE_ENTRY AS "APP_TERM",  
            SA.SARADAP_ADMT_CODE AS "ADM_TYPE",
            ST.SARAATT_TERM_CODE AS "TERM_CODE",
            ST.SARAATT_APPL_NO "APPL_NO1",
            SA.SARADAP_APPL_NO "APPL_NO2"
    FROM 
        SPRIDEN SP
        JOIN SARADAP SA
        ON SP.SPRIDEN_PIDM = SA.SARADAP_PIDM
        JOIN SORLCUR SR
        ON SP.SPRIDEN_PIDM = SR.SORLCUR_PIDM
        LEFT OUTER JOIN SARAATT ST
        ON SP.SPRIDEN_PIDM = ST.SARAATT_PIDM
    WHERE 
        SP.SPRIDEN_CHANGE_IND IS NULL
        AND SA.SARADAP_ADMT_CODE IN ('SP', 'XT' )
)
SELECT
    ID,
    LAST,
    FIRST,
    APP_TERM,
    ADM_TYPE,
    TERM_CODE,
    APPL_NO1,
    APPL_NO2,
    CASE
    WHEN (SELECT
           COUNT(1)
         FROM
           t t2
         WHERE
           t1.APPL_NO2=t2.APPL_NO1) = 0 THEN 'NO WSP'
    END AS "My Report Column"
FROM
    t t1;

我没有对此进行过语法错误测试,因此请随时纠正它们。我确信对此有一个分析函数解决方案,但我认为这应该也可以。

【讨论】:

  • 感谢您的回答。在我明天上班之前我无法测试它。这就是我需要的:查看 ST.SARAATT_APPL_NO 和 SA.SARADAP_APPL_NO 两列。发现 SARADAP_APPL_NO= 2 和 SARADAP_APPL_NO=5 行在任何 SARAATT_APPL_NO 行中都没有匹配项。拉出那些没有匹配的行。我明天会测试这个。我希望你能回来看看。 :)
  • @AuntieAnita:当然,检查并告诉我。上述查询不会过滤掉 SARAATT_APPL_NO = SARADAP_APPL_NO 的记录。相反,它将显示所有记录(如您在问题中所述),其中所需记录(即,SARADAP_APPL_NO SARAATT_APPL_NO)具有“无 WSP”值,而其他记录的“我的报告列”将为 NULL。跨度>
  • :( 如果两列字面上不匹配,则表示 NO WSP。它需要这样做:查看第 2 列中的值,第 1 行 (C2R1) 是 C1 中某处的值?否, print "NO WSP" in My Report Column -- C2R2 in C1? no, print No WSP -- C2R3 in C1? Yes, print nothing, etc... 所以,它需要查看 C2 中的每个值,看看是否它在 C1 中,然后决定是否打印“No WSP”
  • 我添加了另一张图片来解释我希望做什么。我相信我的要求会使脚本运行缓慢,但这是我能想到的唯一方法,它将返回我需要的数据。此外,一旦我从 SELECT 语句中删除了 APPL_NO 和 SARAATT 术语列,它将消除所有重复的行并让我得到我想要的。
  • @AuntieAnita:根据您的评论更新了答案。
【解决方案2】:

** 感谢 Todderlmenot (https://stackoverflow.com/users/350136/toddlermenot) 付出的所有时间和努力!你帮我解决了一半的问题,在这个过程中学到了很多东西! 另外,感谢 Vignesh Lakshmirajan 帮我解决了另一半问题**

事实证明,我可以使用MINUS 来确定列中缺少的行。

/*
Author: 
Date: 30-Sep-14
Purpose: Select records of Special or Transient applicants whose Attribute field (SAAADMS - Contacts, Cohorts, Attributes) does contain "WSP"

NOTE: For those records missing the WSP, there will be no rows in SARAATT for the term/application number in which WPS is missing.  
Those rows will simply not exist.   

SARADAP_TERM    SARADAP_APPL    SARAATT_TERM    SARAATT_APPL    SARAATT_ATTS_CODE    
    200810          2               200810          2               WPS
    200910          3                       
    201080          4               201080          4               WPS
    201350          5                    

Use SARADAP MINUS SARAATT to retreive the rows for which there is no SARAATT.  
We can use this becuase for rows in which there is no WSP, there will also be no APPL_NO or TERM_CODE       
*/



Select  
sp.spriden_id as "ID", 
SP.SPRIDEN_LAST_NAME as "Last", 
SP.SPRIDEN_FIRST_NAME as "First", 
SA.SARADAP_TERM_CODE_ENTRY as "SARADAP_TERM_CODE_ENTRY",  
sa.SARADAP_APPL_NO as "SARADAP_APPL_NO"

FROM     
SPRIDEN SP
JOIN SARADAP SA
on sp.spriden_pidm = sa.saradap_PIDM

WHERE 
Sp.spriden_change_ind is null
AND
SA.SARADAP_TERM_CODE_ENTRY >= '201510'
AND
SA.SARADAP_ADMT_CODE in ('SP', 'XT' )


MINUS


SELECT
sp.spriden_id as "ID", 
SP.SPRIDEN_LAST_NAME as "Last", 
SP.SPRIDEN_FIRST_NAME as "First",
st.SARAATT_TERM_CODE as "SARAATT_TERM_CODE",
st.SARAATT_APPL_NO as "SARAATT_APPL_NO"

FROM 
SPRIDEN SP
LEFT OUTER JOIN SARAATT ST
on sp.spriden_pidm = ST.SARAATT_PIDM

WHERE 
Sp.spriden_change_ind is null

【讨论】:

    猜你喜欢
    • 2016-12-08
    • 2021-07-14
    • 2020-01-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-17
    • 1970-01-01
    • 2016-03-11
    相关资源
    最近更新 更多