Я хочу перебирать столбцы ['A', 'B', 'C'] и передавать имена столбцов оператору выбора в SQL, например
SELECT * FROM table_name
WHERE table_name.`A` IS NULL
Таким образом, каждый оператор выбора будет возвращать набор результатов на основе имени столбца. Это будет содержаться в сценарии sql. Затем я читал каждый результат через соединение с базой данных Python, например mysql-коннектор. Как бы я это сделал? Спасибо!
Изменить. Я хочу сохранить решение строго в рамках SQL.
Если вы хотите сохранить решение строго в sql, то почему ваш вопрос помечен тегом python?
@BillKarwin моя фактическая таблица большая, в ней несколько ТБ данных. Сам запрос тоже не такой простой, как тот, который я разместил. Вот почему я решил, что лучше иметь решение на чистом SQL.
Вам следует задать вопрос с подробной информацией о проблеме, которую вы пытаетесь решить. До сих пор не ясно, зачем вам решение на чистом SQL. Есть детали, которые мы не сможем узнать, пока вы их не объясните.
«получить набор результатов на основе имени столбца», как это выглядит? как вы представляете себе сервер, разделяющий результаты для разных столбцов, или клиент, знающий, что это за результат? здесь нет ничего невозможного, но вы не показываете нам, чего хотите. помните, что выборки sql предназначены для возврата строк, содержащих столбцы, существуют различные способы соответствия информации этому, но вы должны сообщить нам, чего вы ожидаете
Создайте запрос динамически в 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 по другим причинам.
MySQL не имеет хорошего способа перебирать список столбцов, поскольку у него нет типа данных, подобного списку. А чтобы выполнить любой цикл, вам нужно написать хранимую процедуру, которая динамически создает запрос с помощью PREPARE
.
@KidSudi, с базой данных это невозможно. Для этого вам следует использовать язык программирования, такой как Python (как мы это сделали).
@Barmar, проголосовал за твой ответ, так как он почти похож на мой
@Бармар, спасибо тебе за это. Как будет выглядеть решение хранимой процедуры?
Поскольку в MySQL нет массивов, вам придется хранить список столбцов в таблице. Вы можете использовать курсор для перебора запроса из этой таблицы. Затем создайте запрос в строковой переменной и используйте PREPARE STATEMENT
и EXECUTE
для выполнения запросов.
Этого достаточно для общего направления? Пожалуйста, попробуйте, и я помогу вам исправить это, если это не сработает.
Взят пример 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.
Вам следует послушать людей, которые рекомендуют делать это в цикле Python. Я не рекомендую использовать хранимую процедуру, потому что вам придется изучить курсоры, динамические запросы, получение нескольких результатов и подобную ерунду. Затем вы узнаете, что процедуры MySQL не имеют отладчика, модулей, атомарного развертывания или хорошей документации. Поверьте нам — на Python будет проще выполнить цикл. Жизнь слишком коротка, чтобы тратить ее на разработку хранимых процедур MySQL.