Для цикла по определенным столбцам таблицы и перехода к оператору реляционного SQL

Я хочу перебирать столбцы ['A', 'B', 'C'] и передавать имена столбцов оператору выбора в SQL, например

SELECT * FROM table_name
WHERE table_name.`A` IS NULL

Таким образом, каждый оператор выбора будет возвращать набор результатов на основе имени столбца. Это будет содержаться в сценарии sql. Затем я читал каждый результат через соединение с базой данных Python, например mysql-коннектор. Как бы я это сделал? Спасибо!

Изменить. Я хочу сохранить решение строго в рамках SQL.

Вам следует послушать людей, которые рекомендуют делать это в цикле Python. Я не рекомендую использовать хранимую процедуру, потому что вам придется изучить курсоры, динамические запросы, получение нескольких результатов и подобную ерунду. Затем вы узнаете, что процедуры MySQL не имеют отладчика, модулей, атомарного развертывания или хорошей документации. Поверьте нам — на Python будет проще выполнить цикл. Жизнь слишком коротка, чтобы тратить ее на разработку хранимых процедур MySQL.

Bill Karwin 20.08.2024 01:43

Если вы хотите сохранить решение строго в sql, то почему ваш вопрос помечен тегом python?

Shadow 20.08.2024 03:33

@BillKarwin моя фактическая таблица большая, в ней несколько ТБ данных. Сам запрос тоже не такой простой, как тот, который я разместил. Вот почему я решил, что лучше иметь решение на чистом SQL.

KidSudi 20.08.2024 04:03

Вам следует задать вопрос с подробной информацией о проблеме, которую вы пытаетесь решить. До сих пор не ясно, зачем вам решение на чистом SQL. Есть детали, которые мы не сможем узнать, пока вы их не объясните.

Bill Karwin 20.08.2024 05:02

«получить набор результатов на основе имени столбца», как это выглядит? как вы представляете себе сервер, разделяющий результаты для разных столбцов, или клиент, знающий, что это за результат? здесь нет ничего невозможного, но вы не показываете нам, чего хотите. помните, что выборки sql предназначены для возврата строк, содержащих столбцы, существуют различные способы соответствия информации этому, но вы должны сообщить нам, чего вы ожидаете

ysth 20.08.2024 06:14
ReactJs | Supabase | Добавление данных в базу данных
ReactJs | Supabase | Добавление данных в базу данных
Это и есть ваш редактор таблиц в supabase.👇
Понимание Python и переход к SQL
Понимание Python и переход к SQL
Перед нами лабораторная работа по BloodOath:
1
5
65
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Создайте запрос динамически в Python в цикле.

cols = ['A', 'B', 'C']

for col in cols:
    sql = f'SELECT * FROM table_name WHERE `{col}` IS NULL'
    cursor.execute(sql)
    # process the results of the query

Спасибо за ваше решение, однако я хотел сохранить это строго в рамках SQL и вызывать сценарий в Python по другим причинам.

KidSudi 19.08.2024 22:18

MySQL не имеет хорошего способа перебирать список столбцов, поскольку у него нет типа данных, подобного списку. А чтобы выполнить любой цикл, вам нужно написать хранимую процедуру, которая динамически создает запрос с помощью PREPARE.

Barmar 19.08.2024 22:24

@KidSudi, с базой данных это невозможно. Для этого вам следует использовать язык программирования, такой как Python (как мы это сделали).

Suramuthu R 19.08.2024 22:59

@Barmar, проголосовал за твой ответ, так как он почти похож на мой

Suramuthu R 19.08.2024 23:00

@Бармар, спасибо тебе за это. Как будет выглядеть решение хранимой процедуры?

KidSudi 20.08.2024 00:20

Поскольку в MySQL нет массивов, вам придется хранить список столбцов в таблице. Вы можете использовать курсор для перебора запроса из этой таблицы. Затем создайте запрос в строковой переменной и используйте PREPARE STATEMENT и EXECUTE для выполнения запросов.

Barmar 20.08.2024 01:25

Этого достаточно для общего направления? Пожалуйста, попробуйте, и я помогу вам исправить это, если это не сработает.

Barmar 20.08.2024 01:27

Взят пример sqlite. Но запросы будут аналогичны для других последовательных баз данных, таких как mysql или mssql. Ниже будут выполняться запросы для каждого столбца, имеющего значение NULL. И для каждого запроса он создаст 2D-список и сохранит его как значение dict. Ключевые имена dict будут соответствующими именами столбцов. Вы можете обработать данные из dict

import sqlite3

conn = sqlite3.connect('example.db')
cursor = conn.cursor()

dct = {}

columns = ['A', 'B', 'C']

for column in columns:

    qry = f'SELECT * FROM table_name WHERE {column} IS NULL'

    cursor.execute(qry)

    # fetch the results
    r = cursor.fetchall()
    
    # create a 2d list of each colum
    dct[column] = [list(row) for row in r]

conn.close()

Для MySQL вы можете использовать модуль mysql.connector, а для MSSQL — модуль pyodbc для подключения.

Ответ принят как подходящий

Возможно, вы могли бы прочитать все свои данные из базы данных и сгенерировать команды sql. Если я правильно понял, вам нужны сформированные команды sql для получения данных, в которых отдельные столбцы имеют значение NULL.
Давайте создадим две таблицы для работы:

--    S a m p l e    D a t a :
Create Table tbl_1 ( id Int, a Varchar(12), b Varchar(12), c Decimal );
Insert Into tbl_1 VALUES ( 1, 'ABCD', 'EFGH', 3.5 ), 
                         ( 2, 'OPQR',  Null,  1.2 ), 
                         ( 3, Null,   'STUV', 7.1 ),
                         ( 4, 'KLMN', 'WXYZ', Null);

Create Table tbl_2 ( id Int, x Varchar(12), y Varchar(12), z Varchar(12) );
Insert Into tbl_2 VALUES ( 1, 'XX',  'YY', '*' ), 
                         ( 2, 'AA', Null,  '**' ), 
                         ( 3, Null,  'BB', '***'),
                         ( 4, 'CC',  'DD', Null);

... имена столбцов в ваших таблицах можно получить из INFORMATION_SCHEMA.COLUMNS.

WITH
  tbl_cols AS
    ( SELECT   TABLE_NAME, COLUMN_NAME, ORDINAL_POSITION
      FROM     INFORMATION_SCHEMA.COLUMNS
      WHERE    TABLE_SCHEMA = 'your_schema_name' 
               /* And TABLE_NAME = tbl_1 (if you want just that table) */
      ORDER BY TABLE_NAME, ORDINAL_POSITION 
    ), 

... создайте cte для генерации команды sql SELECT для каждого столбца (столбец id исключен в этом ответе)

  cmds AS
    ( Select Row_Number() Over(Order By TABLE_NAME, ORDINAL_POSITION) as id, 
             TABLE_NAME, COLUMN_NAME, 
             Concat( 'Select ', TABLE_NAME, '.*',  
                     ' From ', TABLE_NAME,
                     ' Where ', TABLE_NAME, '.', COLUMN_NAME, ' Is Null'
                   ) as SQL_CMD
      From   tbl_cols
      Where  COLUMN_NAME != 'id'  /* filtering columns here */
    ) 

... получить данные сверху cte

Select * 
From   cmds;
/*    R e s u l t : 
id  TABLE_NAME  COLUMN_NAME  SQL_CMD
--  ----------  -----------  --------------------------------------------------
1   tbl_1       a            Select tbl_1.* From tbl_1 Where tbl_1.a Is Null
2   tbl_1       b            Select tbl_1.* From tbl_1 Where tbl_1.b Is Null
3   tbl_1       c            Select tbl_1.* From tbl_1 Where tbl_1.c Is Null
4   tbl_2       x            Select tbl_2.* From tbl_2 Where tbl_2.x Is Null
5   tbl_2       y            Select tbl_2.* From tbl_2 Where tbl_2.y Is Null
6   tbl_2       z            Select tbl_2.* From tbl_2 Where tbl_2.z Is Null        */

... выше приведен набор команд sql, определенных для каждой таблицы, имеющей код sql для конкретного столбца...

Более того, если вы создадите еще один cte, который будет собирать вышеуказанные команды sql и объединять их для одной и той же таблицы, вы сможете получить все данные таблицы, которые будут получать определенные команды sql...

  cmds_union AS
    ( SELECT   TABLE_NAME, 
               for_columns, 
               REPLACE(SubStr(SQL_CMD, 1, Length(SQL_CMD) - 11), ',', '') as SQL_CMD
      FROM   
      ( Select   TABLE_NAME, 
                 GROUP_CONCAT(COLUMN_NAME) as for_columns,
                 GROUP_CONCAT(SQL_CMD, ' UNION ALL
' )  as SQL_CMD
        From     cmds 
        Group By TABLE_NAME
      ) a
    )
Select * 
From   cmds_union;
/*      R e s u l t : 
TABLE_NAME  for_columns  SQL_CMD
----------  -----------  -------------------------------------------------------
tbl_1       a,b,c        Select tbl_1.* From tbl_1 Where tbl_1.a Is Null UNION ALL
                         Select tbl_1.* From tbl_1 Where tbl_1.b Is Null UNION ALL
                         Select tbl_1.* From tbl_1 Where tbl_1.c Is Null
                         
tbl_2       x,y,z        Select tbl_2.* From tbl_2 Where tbl_2.x Is Null UNION ALL
                         Select tbl_2.* From tbl_2 Where tbl_2.y Is Null UNION ALL
                         Select tbl_2.* From tbl_2 Where tbl_2.z Is Null              */

См. скрипку здесь.

ПРИМЕЧАНИЕ:
Вы можете фильтровать интересующие таблицы/столбцы и/или корректировать код в соответствии с вашими потребностями. Это просто возможный вариант сделать это строго с помощью sql.

Другие вопросы по теме