postgresql高级应用之合并单元格

postgresql高级应用之合并单元格

转载请注明出处https://www.cnblogs.com/funnyzpc/p/14732172.html

1.写在前面✍

继上一篇postgresql高级应用之行转列&汇总求和之后想更进一步做点儿复杂的(圖表暫且不論哈😂),当然作为報表,出現最多的無非就是合并單元格了,是的,我已經迫不及待啦😎~

postgresql高级应用之合并单元格

2.思考

首先,我們的腦海中應該有一個對前端 table有一個大致的了解, 當然這對非前端的同學十分的不友好,如果您嘗試閲讀以下内容存在困難的話(前端 htmljavascript) 可就此打住哈。。。
enn…,讓我先稍稍解釋下前端 html 的表格格式吧😀

2.1 前端 html -> table 基本結構

先給出一個十分base的html demo.html

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>demo</title>
</head>
<body>
  <!-- 這裏定義了兩個屬性 border:定義表格邊框 cellpadding:定義單元格大小 -->
  <table border="3" cellpadding="8">
    <thead>
        <tr>
            <th>&#x8868;&#x982D;1</th><th>&#x8868;&#x982D;2</th><th>&#x8868;&#x982D;3</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>&#x7B2C;&#x4E00;&#x884C;&#x7B2C;1&#x500B;</td><td>&#x7B2C;&#x4E00;&#x884C;&#x7B2C;2&#x500B;</td><td>&#x7B2C;&#x4E00;&#x884C;&#x7B2C;3&#x500B;</td>
        </tr>
        <tr>
            <!-- 使用colspan屬性進行橫向合并,橫向被合并的單元格位置需要騰出來 -->
            <!-- 以下橫向合并兩個單元格,所以第二個td標簽就不要寫了,否則會溢出哦~ -->
            <td colspan="2">&#x6A6B;&#x5411;&#x5408;&#x5E76;&#x4E86;&#x5169;&#x500B;&#x55AE;&#x5143;&#x683C;</td><td>&#x7B2C;&#x4E8C;&#x884C;&#x7B2C;3&#x500B;</td>
        </tr>
        <tr>
            <td>&#x7B2C;&#x4E09;&#x884C;&#x7B2C;1&#x500B;</td><td>&#x7B2C;&#x4E09;&#x884C;&#x7B2C;2&#x500B;</td><td>&#x7B2C;&#x4E09;&#x884C;&#x7B2C;3&#x500B;</td>
        </tr>
        <tr>
            <!-- 使用rowspan屬性進行縱向合并,縱向合并的(跨越的)單元格位置需要騰出來 -->
            <!-- 以下縱向合并三個個單元格(在本行最後一個標簽),所以下兩行的最後兩個td標簽就不要寫啦~,否則同樣會溢出哦~ -->
            <td>&#x7B2C;&#x56DB;&#x884C;&#x7B2C;1&#x500B;</td><td>&#x7B2C;&#x56DB;&#x884C;&#x7B2C;2&#x500B;</td><td rowspan="3">&#x7E31;&#x5411;&#x5408;&#x5E76;&#x4E86;&#x4E09;&#x500B;&#x55AE;&#x5143;&#x683C;</td>
        </tr>
        <tr>
            <td>&#x7B2C;&#x4E94;&#x884C;&#x7B2C;1&#x500B;</td><td>&#x7B2C;&#x4E94;&#x884C;&#x7B2C;2&#x500B;</td>
        </tr>
        <tr>
            <td>&#x7B2C;&#x516D;&#x884C;&#x7B2C;1&#x500B;</td><td>&#x7B2C;&#x516D;&#x884C;&#x7B2C;2&#x500B;</td>
        </tr>
    </tbody>
  </table>
</body>
</html>

瀏覽器渲染出來(使用瀏覽器打開html文件)的樣子是這樣的~

postgresql高级应用之合并单元格

以上總結就是 colspan實現橫向合并單元格, rowspan實現縱向合并單元格~

呃嗯,既然我們知道了 html需要這兩個屬性值(也就是合并的行數或合并的列數),那麽就是要在sql中生成這兩個參數值然後提供給前端的同學使用哈,這是淺層意思,那麽深層意思是什麽呢???容我想想看。。。

  • 對於橫向合并單元格 需要使用 case+ when+ then 語句判斷是否需要橫向合并(重要的是要給出橫向合并的數值),這樣想是合理的,可能造成的困擾可能是這樣做會造成 sql冗餘(當然也是不得已而爲之),當然本節就不再講橫向合并單元格啦
  • 對於縱向合并單元格 step1.👉 如果使用 &#x805A;&#x5408;+ &#x7A97;&#x53E3;&#x51FD;&#x6578;來計算需要合并的相同的列數,可能造成的問題是生成的 rowspan對於相同列來説數值是一樣的(如下圖),這樣不可以欸~
    postgresql高级应用之合并单元格
    倒排序的窗口列
    postgresql高级应用之合并单元格
    求總的列+倒排序的列
    postgresql高级应用之合并单元格
    postgresql高级应用之合并单元格

2.2表结构

drop table if EXISTS  report2 ;
CREATE TABLE report2 (
  "id" varchar(10) primary key,
  "name" varchar(50),
  "price" numeric,
  "level2" varchar(50) ,
  "level1" varchar(50)
);

2.3表字段注释

字段 注释 id 主键 name 商品名称 price 价格 level2 二级分类 level1 一级分类

2.4表数据

INSERT INTO "report2"("id", "name", "price", "level2", "level1") VALUES ('0015', '&#x6D17;&#x53D1;&#x9732;', '36', '&#x6D17;&#x62A4;', '&#x65E5;&#x7528;&#x54C1;');
INSERT INTO "report2"("id", "name", "price", "level2", "level1") VALUES ('0008', '&#x9999;&#x7682;', '17.5', '&#x6D17;&#x62A4;', '&#x65E5;&#x7528;&#x54C1;');
INSERT INTO "report2"("id", "name", "price", "level2", "level1") VALUES ('0007', '&#x85AF;&#x6761;', '7.5', '&#x5783;&#x573E;&#x98DF;&#x54C1;', '&#x96F6;&#x98DF;');
INSERT INTO "report2"("id", "name", "price", "level2", "level1") VALUES ('0009', '&#x65B9;&#x4FBF;&#x9762;', '3.5', '&#x5783;&#x573E;&#x98DF;&#x54C1;', '&#x96F6;&#x98DF;');
INSERT INTO "report2"("id", "name", "price", "level2", "level1") VALUES ('0004', '&#x8FA3;&#x6761;', '5.6', '&#x5783;&#x573E;&#x98DF;&#x54C1;', '&#x96F6;&#x98DF;');
INSERT INTO "report2"("id", "name", "price", "level2", "level1") VALUES ('0006', 'iPhone X', '9600', '&#x5C0F;&#x7535;&#x5668;', '&#x7535;&#x5668;');
INSERT INTO "report2"("id", "name", "price", "level2", "level1") VALUES ('0003', '&#x624B;&#x8868;', '1237.55', '&#x5C0F;&#x7535;&#x5668;', '&#x7535;&#x5668;');
INSERT INTO "report2"("id", "name", "price", "level2", "level1") VALUES ('0012', '&#x7535;&#x89C6;', '3299', '&#x5927;&#x7535;&#x5668;', '&#x7535;&#x5668;');
INSERT INTO "report2"("id", "name", "price", "level2", "level1") VALUES ('0016', '&#x6D17;&#x8863;&#x673A;', '4999', '&#x5927;&#x7535;&#x5668;', '&#x7535;&#x5668;');
INSERT INTO "report2"("id", "name", "price", "level2", "level1") VALUES ('0013', '&#x56F4;&#x5DFE;', '93', '&#x914D;&#x9970;', '&#x670D;&#x88C5;&#x914D;&#x9970;');
INSERT INTO "report2"("id", "name", "price", "level2", "level1") VALUES ('0017', '&#x7279;&#x6B65;&#x51C9;&#x978B;', '499', '&#x978B;&#x5B50;', '&#x670D;&#x88C5;&#x914D;&#x9970;');
INSERT INTO "report2"("id", "name", "price", "level2", "level1") VALUES ('0001', 'NIKE&#x65B0;&#x6B3E;&#x978B;', '900', '&#x978B;&#x5B50;', '&#x670D;&#x88C5;&#x914D;&#x9970;');
INSERT INTO "report2"("id", "name", "price", "level2", "level1") VALUES ('0002', '&#x5916;&#x5957;', '110.9', '&#x4E0A;&#x8863;', '&#x670D;&#x88C5;&#x914D;&#x9970;');
INSERT INTO "report2"("id", "name", "price", "level2", "level1") VALUES ('0014', '&#x4F5C;&#x4E1A;&#x672C;', '1', '&#x7EB8;&#x5F20;', '&#x6587;&#x5177;');
INSERT INTO "report2"("id", "name", "price", "level2", "level1") VALUES ('0005', '&#x94C5;&#x7B14;', '7', '&#x7B14;', '&#x6587;&#x5177;');
INSERT INTO "report2"("id", "name", "price", "level2", "level1") VALUES ('0010', '&#x6C34;&#x676F;', '27', '&#x9910;&#x996E;', '&#x65E5;&#x7528;&#x54C1;');
INSERT INTO "report2"("id", "name", "price", "level2", "level1") VALUES ('0011', '&#x6BDB;&#x5DFE;', '15', '&#x6D17;&#x62A4;', '&#x65E5;&#x7528;&#x54C1;');
INSERT INTO "report2"("id", "name", "price", "level2", "level1") VALUES ('0018', '&#x7ED8;&#x56FE;&#x7B14;', '15', '&#x7B14;', '&#x6587;&#x5177;');
INSERT INTO "report2"("id", "name", "price", "level2", "level1") VALUES ('0019', '&#x6C7D;&#x6C34;', '3.5', '&#x5176;&#x5B83;', '&#x96F6;&#x98DF;');

3.🎉結果集最終求解

select
  t1.*,
  case when  t_rank=t_count then t_count else null end as level1_row,
  case when  tu_rank=tu_count then tu_count else null end as level2_row
from
(
    select
      *,
      row_number() over(PARTITION by level1 order by level1 asc) t_rank,
      count(1) over (partition by level1) t_count,
      row_number() over(PARTITION by level1,level2 order by level1,level2 asc) tu_rank,
      count(1) over (partition by level1,level2) tu_count
    from report2 order by level1
) t1 order by t1.level1,t_rank desc,t_count desc,tu_rank desc,tu_count desc;

_紅色_部分即為前端童鞋需要的合并數值哈🥰~

postgresql高级应用之合并单元格

如果你能看懂以上問題及求解的 sql ,恭喜你又升級啦😂

總結下::對問題的 &#x5206;&#x6790;&#x2728;以及對問題求解的 &#x601D;&#x8003;&#x1F914;很重要嘛,當然還包含對 postgresql所提供工具的靈活使用 👉 總會產生意想不到的驚喜,哈哈😘~

Original: https://www.cnblogs.com/funnyzpc/p/14732172.html
Author: funnyZpC
Title: postgresql高级应用之合并单元格

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/562396/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球