Параметризованный запрос из Excel с предложением IN - PullRequest
0 голосов
/ 24 мая 2019

У меня есть MS Query соединение от Excel 2016 листа до IBM DB2 базы данных. Я использую параметризованные значения запроса и ссылки на ячейку Excel. Хотя «особые значения», такие как = < > like, работают, я не могу заставить IN работать с несколькими значениями , но в остальном супер простой запрос.

Вот простой демонстрационный набор данных о том, как я создаю значения параметров:

enter image description here

Формула столбца D - =IF(C2>5,A2&",",""), которая проверяет значение столбца C на более чем 5 и заполняет ID в столбце D, если TRUE. Я ожидаю использовать вспомогательную ячейку для объединения / объединения всех значений в столбце D, которые я хочу использовать для предложения IN в качестве значения ( еще не завершено ).

Как я могу использовать "value1, value2, value3, ..." в ячейке для выполнения запроса предложения IN? Возможно ли это вообще? IN Предложение отлично работает, когда связанная ячейка содержит значение 1, однако 1, 3 выдает сообщение об ошибке: "Bad parameter type. Microsoft Excel is expecting a different kind of value than what was provided".

Использование отдельного параметра и условия OR для каждой ячейки технически выглядит работоспособным, однако на практике набор данных может легко достигать 50-100 значений, что означает сумасшедший объем настройки параметров.

Сам запрос такой же простой, как:

select * from PRODUCTS a
where a.prod_ID in (1,3)

или как альтернатива Excel MS Query:

select * from PRODUCTS a
where a.prod_ID in ?

Ответы [ 2 ]

1 голос
/ 24 мая 2019

Это:

select * from PRODUCTS a
where a.prod_ID in ?

никогда не будет работать.

Что бы сработало, передача строки в функцию, которая может возвращать набор строк.

select * 
from PRODUCTS a
where a.prod_ID in (select int(column_value)
                    from table ( split(?,',')) tbl
                   )

split() - это пользовательская табличная функция, взятая из рабочей статьи разработчика IBM: Как разбить строку на набор строк (anti-LISTAGG)

CREATE OR REPLACE FUNCTION SPLIT(text VARCHAR(32000), split VARCHAR(10))
RETURNS TABLE(column_values VARCHAR(60))
RETURN WITH rec(rn, column_value, pos) AS
        (VALUES (1, VARCHAR(SUBSTR(text, 1, 
                                   DECODE(INSTR(text, split, 1), 
                                          0, 
                                          LENGTH(text), 
                                          INSTR(text, split, 1) - 1)),
                            255),  
                    INSTR(text, split, 1) + LENGTH(split))
         UNION ALL
         SELECT rn + 1, VARCHAR(SUBSTR(text, pos, 
                                       DECODE(INSTR(text, split, pos), 
                                              0, 
                                              LENGTH(text) - pos + 1,  
                                              INSTR(text, split, pos) - pos)), 
                                255),  
                        INSTR(text, split, pos) + LENGTH(split)
          FROM rec WHERE rn < 30000 AND pos > LENGTH(split))
      SELECT column_value FROM rec;

В зависимости от вашей платформы и версии Db2 могут быть некоторые встроенные опции.

Например, в последних версиях вы можете передать строку XML или JSON со значениями и использовать XMLTABLE () или JSON_TABLE (), чтобы разбить строку на строки.

0 голосов
/ 26 мая 2019

разместив это здесь для будущих гуглеров. Таким образом, решение было немного из коробки для меня - хотя все еще нуждается в улучшении.

Он проверяет наличие событий изменения листа в диапазоне M1: M4, а затем заполняет текст команды запроса IN-предложения в соответствии с подготовленным синтаксисом в B1. Действительно из коробки для меня!

К сожалению, здесь обрабатывается только один объект Listobject (1), хотя у меня есть несколько таких, которые должны получить одинаковую обработку - но, тем не менее, отличные вещи.

Private Sub Worksheet_Change(ByVal Target As Range)

    Dim INvaluesCell As Range
    Dim SQLin As String, parts As Variant
    Dim i As Long, p1 As Long, p2 As Long
    Dim qt As QueryTable

    Set INvaluesCell = Range("B1")

    If Not Intersect(Target, Range(INvaluesCell, "M1:M4")) Is Nothing Then

        SQLin = ""
        parts = Split(INvaluesCell.Value, ",")
        For i = 0 To UBound(parts)
            SQLin = SQLin & "'" & parts(i) & "',"
        Next
        SQLin = " IN (" & Left(SQLin, Len(SQLin) - 1) & ")"

        Set qt = Me.ListObjects(1).QueryTable

        p1 = InStr(1, qt.CommandText, " IN (", vbTextCompare)
        If p1 > 0 Then
            p2 = InStr(p1, qt.CommandText, ")") + 1
            qt.CommandText = Left(qt.CommandText, p1 - 1) & SQLin & Mid(qt.CommandText, p2)
        End If

    End If

End Sub
...