簡體   English   中英

如何使用 SQLite 模擬 LPAD/RPAD

[英]How to emulate LPAD/RPAD with SQLite

我很好奇如何以最一般的方式正式模擬 SQLite 的 RPAD 和 LPAD 功能。 目標是能夠做到

LPAD(column, character, repeat)
RPAD(column, character, repeat)

對於非常量表列columncharacterrepeat 如果characterrepeat是已知的常量,那么這將是一個很好的、可行的解決方案:

但是如果上面應該這樣執行怎么辦:

SELECT LPAD(t.column, t.character, t.repeat) FROM t
SELECT LPAD(t.column, some_function(), some_other_function()) FROM t
SELECT LPAD(t.column, :some_bind_variable, :some_other_bind_variable) FROM t

這個LPAD function 通常如何被仿真? 我迷失了各種可能性:

一個相關的問題:

復制自http://verysimple.com/2010/01/12/sqlite-lpad-rpad-function/

-- the statement below is almost the same as
-- select lpad(mycolumn,'0',10) from mytable

select substr('0000000000' || mycolumn, -10, 10) from mytable

-- the statement below is almost the same as
-- select rpad(mycolumn,'0',10) from mytable

select substr(mycolumn || '0000000000', 1, 10) from mytable

您也可以使用 PRINTF。

sqlite> SELECT PRINTF('%02d',5);
05
sqlite> SELECT PRINTF('%04d%02d',25,5);
002505
sqlite> 

@user610650 解決方案的更簡單版本,使用 hex() 而不是 quote(),除了字符填充外,還可以使用字符串填充:

X = padToLength
Y = padString
Z = expression

select
    Z ||
    substr(
        replace(
            hex(zeroblob(X)),
            '00',
            Y
        ),
        1,
        X - length(Z)
    );

這里對你來說更討厭:

X = padToLength
Y = padString
Z = expression

RPAD(對於 LPAD,Z 在之后連接):

select 
    Z || 
    substr(
        replace(
            replace(
                substr(
                    quote(zeroblob(((X - length(Z) - 1 + length(Y)) / length(Y) + 1) / 2)), 
                    3
                ), 
                "'", 
                ""
            ), 
            "0", 
            Y
        ),
        1,
        (X - length(Z))
    )

例子:

sqlite> select "foo" || replace(replace(substr(quote(zeroblob((2 + 1) / 2)), 3, (2 - length("foo"))), "'", ""), "0", "W");
foo
sqlite> select "foo" || replace(replace(substr(quote(zeroblob((7 + 1) / 2)), 3, (7 - length("foo"))), "'", ""), "0", "W");
fooWWWW

Sqlite 本來就是輕量級的,所以我不得不對你對缺乏功能感到“驚訝”的評論有些不同意。 但是,我同意應該有一種更簡單的方法來進行填充,如果只是因為存在trim功能。

JDBC/自定義函數方法(可能不適合您的具體情況,但可能能夠適應)。 使用來自SqliteJDBC 自定義函數以及來自 Apache commons.lang.StringUtils 的rightPadleftPad函數的靈感:

import java.sql.*;
import org.sqlite.Function;

public class Test 
{
  public static void main(String[] args) 
  {
    Connection conn = getConnection();

    conn.createStatement().execute("SELECT LPAD(t.column, t.character, t.repeat) FROM t");
    conn.createStatement().execute("SELECT RPAD(t.column, t.character, t.repeat) FROM t");

    conn.close();
  }

  public static Connection getConnection() 
  {
    Class.forName("org.sqlite.JDBC");
    Connection conn = DriverManager.getConnection("jdbc:sqlite:");

    /* Left Padding UDF  */
    Function.create(conn, "LPAD", new Function() 
      {
        protected void xFunc() throws SQLException 
        {
            String text = value_text(0);
            /* uses first character of supplied padding */
            char paddingCharacter = value_text(1).charAt(0);
            int repeat = value_int(2);

            int padLength = repeat - text.length();
            if(padLength <= 0)
            {
               result(text);
            }

            char[] padding = new char[padLength];
            Array.fill(padding, paddingCharacter);
            result(new String(padding).append(text));
        }
    });

    /* Right Padding UDF  */
    Function.create(conn, "RPAD", new Function() 
      {
        protected void xFunc() throws SQLException 
        {
            String text = value_text(0);
            /* uses first character of supplied padding */
            char paddingCharacter = value_text(1).charAt(0);
            int repeat = value_int(2);

            int padLength = repeat - text.length();
            if(padLength <= 0)
            {
               result(text);
            }

            char[] padding = new char[padLength];
            Array.fill(padding, paddingCharacter);
            result(text.append(new String(padding)));
        }
    });
  }
}

(未經測試,即興發揮,不處理空值等,但應該概述這個想法......)

她是使用 CASE 用前導零填充 0-9 的簡單解決方案。

sqlite> select id,week,year from bulletin where id = 67;
67|2|2014

select id,CASE WHEN length(week) = 2 THEN week 
               ELSE '0'||week 
          END AS week,year from bulletin where id = 67;
67|02|2014

我絕對沒有 SQLite 的經驗,實際上我與 SQLite3 db 交互的時間只有不到三天。 所以我不確定我的發現對你的要求有什么幫助。

我正在玩一些有趣的項目,即擁有所有可能的 11 位電話號碼(3 位運營商前綴 + 8 位用戶號碼)。 我的目標是創建某種具有盡可能少的存儲資源的數據庫,但必須涵蓋數據庫上所有可能的數字。 所以我為 8 位訂戶創建了一個表,另一個表包含 3 位公司前綴。 最終數字將出現在連接兩個表數據的視圖中。 讓我專注於 LOAD 問題。 由於訂閱者表列是 INT,它是 0 到 99999999 條記錄。 用戶數少於 10000000 的簡單加入失敗; 任何低於 10000000 的訂閱者訂閱 ID 號都會顯示為 XXXprefix+11,其中預期為 XXX000000+11。

在 SQLite 上使用 LPAD/RPAD 失敗后,我找到了“SUBSTR”!

看看下面的查詢:

CREATE TABLE subs_num (
subscriber_num integer PRIMARY KEY
);

INSERT INTO subs_num values ('1');
INSERT INTO subs_num values ('10');
INSERT INTO subs_num values ('100');
INSERT INTO subs_num values ('1000');

SELECT subscriber_num from subs_num;

SELECT SUBSTR('00000000' || subscriber_num, -8, 8) AS SUBSCRIB_ID FROM subs_num;

現在我認為您可以使用 SUBSTR 來滿足您的 LPAD/RPAD 需求。

干杯!

也許是這樣的:

  • LPAD(@orig_text, @padding_char, @padding_length)

     SELECT SUBSTR( REPLACE( CAST(ZEROBLOB(@padding_length) AS TEXT), CAST(ZEROBLOB(1) AS TEXT), @padding_char ) + @orig_text, -@padding_length, @paadding_length )
  • RPAD(@orig_text, @padding_char, @padding_length)

     SELECT SUBSTR( @orig_text + REPLACE( CAST(ZEROBLOB(@padding_length) AS TEXT), CAST(ZEROBLOB(1) AS TEXT), @padding_char ), 1, @padding_length )

printf 也適用於空格:

SELECT 'text lpad 20 "'||printf("%020s", 'text')||'"'  paddedtxt UNION
SELECT 'text rpad 20 "'||printf("%-020s", 'text')||'"' paddedtxt UNION
SELECT 'num  lpad 20 "'||printf("%020d", 42)||'"'      paddedtxt

結果到

num  lpad 20 "00000000000000000042"
text lpad 20 "                text"
text rpad 20 "text                "

目標:使用可用的 sqlite 函數來模擬 ltrim

做法:(1)使用concat function "||" 在字符串的左側添加零(或任何所需的填充字符),添加等於您想要剩余的字符數的零,然后在右側添加零。 (2) 使用 substring 保持所需的字符數。

示例:將 page_number 填充為 integer 左側為零,以在左側填充五個字符零:

select

substring(('00000' || cast(page_number as text) || '0'), -1, -5)

來自分類 = xxx' 的頁面

評論:substring 從 -1 開始時似乎忽略了最后一個字符,這就是為什么我在右邊添加了一個零 - 所以它可以被忽略。 可能有一種更優雅的方式來做到這一點。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM