Oracle SQL-多列上的最常见值

sshcrbum  于 2023-06-22  发布在  Oracle
关注(0)|答案(4)|浏览(130)

我试图弄清楚如何返回一些值,此外,还有几个值需要被指示为最频繁/常见。我将所有这些值存储在几个表中,需要将这些表相互连接。以下是我目前的陈述:

Select distinct
  W.name,
  D.prprty,
  D.sequence_number,
  D.item_num,
  f.grade,
  f.od_inch,
  count(F.od_inch) over (partition by F.prprty, F.sequence_number) as od_count,
  count(f.grade) over (partition by F.prprty, F.sequence_number) as grade_count
FROM table D,
     table W,
     table F
where D.prprty = W.prprty
  and w.prprty = F.prprty
  and W.prprty  =7000
order by sequence_number, od_count desc, grade_count desc

每个属性的值如下所示:

  • 房产x*

序号:1,物料编号:1,等级:10,外径_英寸:2
序号:1,物料编号:2,等级:1,外径_英寸:2
序号:1,项目号:3,等级:10,外径_英寸:1
序号:2,项目号:1,等级:10,外径_英寸:2
序号:2,项目编号:2,等级:10,外径_英寸:5
序号:3,项目号:1,等级:5,外径_英寸:2
目标是返回序列号以及该特定序列号的最常用坡率值和OD_inch值,而不管有多少个项目。
目标:
序列1:最常见等级:10、Most_common_od:2
序列2:最常见等级:10、Most_common_od:2
序列3:最常见等级:5、Most_common_od:2
我需要对现有的查询做些什么来确保它只提取每个序列号一次,并且是最常见的值?

35g0bw71

35g0bw711#

简化,假设只涉及一个表:property

SQL> select * from property;

       SEQ       ITEM      GRADE    OD_INCH
---------- ---------- ---------- ----------
         1          1         10          2
         1          2          1          2
         1          3         10          1
         2          1         10          2
         2          2         10          5
         3          1          5          2

6 rows selected.

此选项需要几个步骤(阅读代码中的注解):计算每个GRADEOD_INCH的行数,然后按降序排序,最后返回排名最高的行数。
注意row_number只返回一行;对于seq = 2od_inch = 25都排名为“最高”(因为它们每个出现一次),但是-似乎你希望在最终结果中只得到一个。如果改变主意,请改用rank解析函数。

SQL> with temp as
  2    -- count number of each GRADE and OD_INCH values
  3    (select seq, grade, od_inch,
  4       count(*) over (partition by seq, grade) cnt_grade,
  5       count(*) over (partition by seq, od_inch) cnt_od
  6     from property
  7    ),
  8  temp2 as
  9    -- now, sort rows by previously counted values
 10    (select seq, grade, od_inch,
 11       row_number() over (partition by seq order by cnt_grade desc) rnk_grade,
 12       row_number() over (partition by seq order by cnt_od desc) rnk_od
 13     from temp
 14    )
 15  -- finally, select the ones that ranked as the highest
 16  select seq,
 17    max(case when rnk_grade = 1 then grade   end) grade,
 18    max(case when rnk_od    = 1 then od_inch end) od_inch
 19  from temp2
 20  where rnk_grade = 1
 21     or rnk_od = 1
 22  group by seq;

       SEQ      GRADE    OD_INCH
---------- ---------- ----------
         1         10          2
         2         10          2
         3          5          2

SQL>

那你会怎么做使用当前查询作为CTE(在我的示例中是temp),对行进行排名并获取排名最高的行。

nkoocmlb

nkoocmlb2#

这会给予你分数

SELECT prprty, grade, count(*) as c
FROM F
GROUP BY prprty, grade

现在我们可以求出这些项的max

SELECT prprty, grade, C
FROM (
  SELECT prprty, grade, C, ROW_NUMBER() OVER (PARTITION BY prprty, grade ORDER BY C DESC as rn
  FROM (
    SELECT prprty, grade, count(*) as c
    FROM F
    GROUP BY prprty, grade
  ) x
  WHERE RN = 1
) z

您可以对od_inch执行相同的操作

SELECT prprty, od_inch, C
FROM (
  SELECT prprty, od_inch, C, ROW_NUMBER() OVER (PARTITION BY prprty, grade ORDER BY C DESC as rn
  FROM (
    SELECT prprty, od_inch, count(*) as c
    FROM F
    GROUP BY prprty, od_inch
  ) x
  WHERE RN = 1
) Z

将它们结合在一起,以获得您的结果:

WITH most_grade AS (
  SELECT prprty, grade, C
  FROM (
    SELECT prprty, grade, C, ROW_NUMBER() OVER (PARTITION BY prprty, grade ORDER BY C DESC as rn
    FROM (
      SELECT prprty, grade, count(*) as c
      FROM F
      GROUP BY prprty, grade
    ) x
    WHERE RN = 1
  ) z
), most_inch AS (
  SELECT prprty, od_inch, C
  FROM (
    SELECT prprty, od_inch, C, ROW_NUMBER() OVER (PARTITION BY prprty, grade ORDER BY C DESC as rn
    FROM (
      SELECT prprty, od_inch, count(*) as c
      FROM F
      GROUP BY prprty, od_inch
    ) x
    WHERE RN = 1
  ) Z
)
SELECT 
  D.prprty,
  D.sequence_number,
  most_grade.grade as most_grade,
  most_grade.C as most_grade_count,
  most_inch.inch as most_inch,
  most_inch.C as most_inch_count
FROM D 
LEFT JOIN most_grade ON most_grade.prprty = D.prprty
LEFT JOIN most_inch  ON most_inch.prprty = D.prprty
tzxcd3kk

tzxcd3kk3#

您可以使用查询,然后使用COUNT(*) OVER (PARTITION BY sequence_number, od_count)的分析函数来查找每个sequence_numberod_counts的频率,然后使用RANK分析函数按该值进行排名,并使用FETCH FIRST ROW WITH TIES查找排名最高的行:

SELECT *
FROM   (
  SELECT t.*,
         COUNT(*) OVER (PARTITION BY sequence_number, od_count) AS cnt
  FROM   (
    Select distinct
           W.name,
           D.prprty,
           D.sequence_number,
           D.item_num,
           f.grade,
           f.od_inch,
           count(F.od_inch) over (partition by F.prprty, F.sequence_number) as od_count,
           count(f.grade) over (partition by F.prprty, F.sequence_number) as grade_count
    FROM   D
           INNER JOIN W
           ON D.prprty = W.prprty
           INNER JOIN F
           ON d.prprty = F.prprty AND d.sequence_number = f.sequence_number
    where  w.prprty = 7000
  ) t
)
ORDER BY RANK() OVER (PARTITION BY sequence_number ORDER BY cnt DESC)
FETCH FIRST ROW WITH TIES;
pinkon5k

pinkon5k4#

张贴答案,因为我尝试了所有其他建议的解决方案,他们不太工作。也许是数据集或操作员错误,但这是提供最佳结果的解决方案(此外,请原谅语法问题... Oracle SQL不是我最强的语言,我也不是一个铁杆的编码员):
1.1、1、2、3、4、5、6、7、8、10、11、12、13、14、15、15、16、16、17、18、19、19、19、19、19、19、19、19、19、19、19、19、19、19、19、19、19、19、19、19、19、19、19、19、19、19、19、19、19、19、19、19、19、19、19、19、19、19、19、19、19、19、19、19、19、19、19、19、19、19、19、19、19、19、19、19、19、19、19、19、19、19、19、19、19、19
选择
D. prprty,
D.序列号,

  • stats_mode(F. grade)as Most_Common_Grade,

stats_mode(F. od_inch)as Most_Common_OD_Inch**(stats_mode是一个巨大的突破,因为否则会返回多行)***
来自表D、表F
在哪里D. prprty!= 0
且D. prprty = F. prprty
按D. prprty,D. Sequence_number分组
order by D.序列号

选择
W. prprty,
CTE1.sequence_number,
CTE1.Most_Common_Grade,
CTE1.Most_Common_OD_英寸
来自表W,cte1
其中w. prprty = cte1.prprty
按cte1.prprty,CTE1.sequence_number排序

相关问题