Подтвердить что ты не робот

В соединении, как префикс всех имен столбцов с таблицей, из которой он пришел

Я анализирую довольно ужасную устаревшую базу данных/кодовую базу, пытаясь уменьшить нагрузку на сервер, объединяя запросы в соединения (включая задание электронной почты по электронной почте, которое обычно вызывает более миллиона отдельных запросов).

SELECT * FROM 
class_alerts_holding ah 
INNER JOIN class_listings l ON l.id = ah.lid 
INNER JOIN class_users u ON u.id = ah.uid
LEFT JOIN class_prodimages pi ON pi.pid = ah.lid

Это выливает 120 столбцов...

aid | id | lid | uid | oid | catName | searchtext | alertfreq | listType | id | owner | title | section | shortDescription | description | featured | price | display | hitcount | dateadded | expiration | url | notified | searchcount | repliedcount | pBold | pHighlighted | notes | ...

Чтобы помочь мне проанализировать, как построить новые запросы, было бы замечательно, если бы я мог префикс столбцов в результате с таблицей, из которой они пришли в JOIN, например.

class_alerts_holding.aid | class_alerts_holding.id | class_listings.lid | ...

Есть ли способ достичь этого?

4b9b3361

Ответ 1

Вы могли

select ah.*, l.*, u.*, pi.* from ...

тогда столбцы будут возвращены по порядку по таблице.

Для лучшего различия между каждыми двумя наборами столбцов вы также можете добавить столбцы "разделитель" следующим образом:

select ah.*, ':', l.*, ':', u.*, ':', pi.* from ...

(Отредактировано, чтобы удалить явные псевдонимы как ненужные, см. комментарии.)

Ответ 2

Вы можете назвать поля в своем запросе и указать им псевдонимы:

SELECT     ah.whateverfield1 AS 'ah_field1',
           ah.whateverfield2 AS 'ah_field2',
           l.whateverfield3 AS 'l.field3',
           [....]
FROM       class_alerts_holding ah 
INNER JOIN class_listings l ON l.id = ah.lid 
INNER JOIN class_users u ON u.id = ah.uid
LEFT JOIN  class_prodimages pi ON pi.pid = ah.lid

Немного о работе для ручной настройки, если у вас есть много полей, но вы можете упростить это с помощью этого запроса...

SHOW FULL FIELDS FROM your_table_name;

... и хороший текстовый редактор, скопируйте и вставьте.

Ответ 3

Способ динамического имени столбцов состоит в создании подготовленного оператора, который ссылается на информационную_схему. Это даст вам результаты, которые вы искали.

SET @sql = NULL;
SELECT CONCAT(
   'SELECT ',GROUP_CONCAT(c.TABLE_NAME,'.',c.COLUMN_NAME,' AS `',c.TABLE_NAME,'.',c.COLUMN_NAME,'`'),'
    FROM class_alerts_holding 
    INNER JOIN class_listings ON class_listings.id = class_alerts_holding.lid 
    INNER JOIN class_users ON class_users.id = class_alerts_holding.uid
    LEFT JOIN class_prodimages ON class_prodimages.pid = class_alerts_holding.lid'
)
INTO @sql
FROM INFORMATION_SCHEMA.COLUMNS c
WHERE c.TABLE_NAME IN ('class_alerts_holding','class_listings',
                       'class_users','class_prodimages');    
PREPARE sql_statement FROM @sql;
EXECUTE sql_statement;

Функция GROUP_CONCAT() имеет ограничение по умолчанию на 1024 символа, поэтому в зависимости от количества столбцов в ваших таблицах вам может потребоваться поднять этот предел, чтобы сгенерировать подготовленный оператор.

SET SESSION group_concat_max_len = 1000000;

При необходимости эта команда поднимет групповой лимит concat. -

Ответ 5

На основе решения, предложенного koljaTM и AndriyM, может быть, даже лучшее решение - написать свой запрос следующим образом:

select
  '--TABLE_AAA:--', TABLE_AAA.*,
  '--TABLE_BBB:--', TABLE_BBB.*,
  '--TABLE_CCC:--', TABLE_CCC.*,
  '--TABLE_DDD:--', TABLE_DDD.*
from ...

К сожалению, это все еще недостаточно хорошо в случаях, когда одна (или более) таблиц содержит больше имен столбцов, чем может поместиться на ширине экрана. (Таким образом, вы можете увидеть на своем экране 20 столбцов, но все еще не видны на экране имя таблицы, из которой они пришли.)

Было бы лучше, если бы SQL предоставил возможность автоматически префикс имен столбцов с именами таблиц...

Ответ 6

@alden-w, вы можете добавить условие TABLE_SCHEMA к тому, чтобы не смешивать одинаковые имена таблиц из разных схем

WHERE c.TABLE_SCHEMA='YOUR_SCHEMA_NAME' AND c.TABLE_NAME IN (....)

Ответ 7

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

declare @col varchar(max)
set @col = Select stuff( 
          (select ', ' + column_name + '.' + table_name 
           from information_schema.columns 
           where table_name in ( 'table1', 'table2' ...) for xml 
           path('')),1,1,'')

declare @query nvarchar(max) = '
select ' + @col + ' 
from table1 
inner join table2 on table1.id = table2.id '

exec sp_executesql @query

Ответ 8

Я убежден, что такая возможность префикса и/или постфикса имен полей с именем таблицы в соединении ДОЛЖНА БЫТЬ ВКЛЮЧЕНА В СТАНДАРТ ANSI SQL. В настоящее время, в 2019 году, до сих пор не существует элегантного кроссплатформенного способа сделать это, и все, что осталось, - уродливый и подверженный ошибкам ручной взлом с использованием псевдонимов или решения для конкретной платформы, включающие динамический sql. Всем было бы полезно иметь возможность указывать свой префикс или/и постфикс для полей, обозначаемых как "точка-звезда" (. *). Выбор образца после добавления такой функции будет:

select a.* use prefix,b.* use postfix '_b' from table_a a inner join table_b b on a.id=b.id

Как видите, по умолчанию префикс или постфикс будут равны имени таблицы (или псевдониму) и могут быть переопределены любым желаемым строковым литералом.

Также то, что нужно добавить к стандарту, - это возможность исключать определенные поля из вывода со звездочкой (*), что является ярлыком для выбора всех полей. Я бы добавил кроме ключевого слова в список файлов, которые я не хочу включать по причинам сокращения передачи данных по сети и/или краткости, например.

select * except large_binary_data_field,another_notneeded_field,etc from my_table

Такая функция позволит избежать необходимости явного указания полного (и потенциально большого) списка полей, которые необходимы, а не только указания звезды и нескольких полей, которые не нужны.

Поэтому, кто бы ни читал этот пост и имел возможность обратиться к влиятельным лицам стандарта ANSI SQL, вы знаете, что делать)

П.С. еще один уродливый, но, по крайней мере, автоматизированный & универсальная динамическая оболочка sql

Для адвокатов Python, работающих с psycopg, я использую удобную подпрограмму (строго внутреннюю, так как она подвержена возможным инъекциям sql)

def get_table_fields(table,alias,prefix='',suffix='',excluding=''):
    if type(excluding)==str: excluding=excluding.split(',')
    cur.execute('select * from '+table+' where 0=1');cur.fetchall()
    if not (cur.description is None):        
        return ','.join([alias+'.'+col.name+' '+prefix+col.name+suffix for col in cur.description if not (col.name in excluding)])

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

sql="""select %s,%s,%s from tasks t,features_sets f,datasets d 
        where 
                t.is_active=true and f.is_active=true 
                and f.task=t.id and t.train_dataset=d.id 
    """ % (
        get_table_fields('tasks','t',prefix='ts_'),
        get_table_fields('features_sets','f',prefix='fs_'),
        get_table_fields('datasets','d',prefix='ds_',excluding='data')
    )

который раскатывается для меня в могучий

select t.id ts_id,t.project ts_project,t.name ts_name,***,
    fs_id,f.task fs_task,f.name fs_name,f.description fs_description,***,
    d.id ds_id,d.project ds_project,d.name ds_name,***
from tasks t,features_sets f,datasets d 
    where 
        t.is_active=true and f.is_active=true 
        and f.task=t.id and t.train_dataset=d.id 

где *** означает множество других полезных полей, некоторые из них являются общими для более чем одной таблицы (отсюда необходимость префикса). cur, очевидно, является курсором psycopg, и условие 0 = 1 предназначено для извлечения только имен полей без реальных данных.