Member 11856456 Ответов: 1

Попытка вызвать конкретную информацию в SQL для отображения


Я нашел общедоступный код, который берет таблицы и отображает их вместе с количеством записей (строк). Я использовал этот код и попытался добавить к нему больше, чтобы можно было заполнить больше полей из каждой таблицы. Проблема в том, что я не могу получить только общее имя столбца, чтобы использовать его, меня постоянно спрашивают, из какой таблицы я хочу извлечь. Я хочу взять общий столбец, который представляет собой год рождения из всех таблиц, и заполнить Listview как год 1, являющийся минимальным годом, и год 2, который является максимальным годом дат в этих таблицах. Я также хочу иметь возможность использовать sys.database в таблице listview, чтобы показать, с какой базой данных связана таблица, когда они просматривают все таблицы сразу.

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

| имя таблицы / записи | год1 | год2 / база данных|


этот код не является полным, так как мне трудно добраться до отдельных имен столбцов, а также использовать sys. database вот код, над которым я работаю:

SELECT 
    [TableName] = so.name, 
    [RowCount] = MAX(si.rows), 
	[databases] = SCH
	[Minimum] = MIN(CMI.),
	[Maximum] = MAX(CMA.number)
	FROM 
    sysobjects so, 
    sysindexes si, 
	sys.databases SCM,
	sys.all_columns CMI,
	syscolumns CMA
WHERE 
    so.xtype = 'U' 
    AND 
    si.id = OBJECT_ID(so.name)
	and
	CMA.
	and
	CMI.
	and 
	SCM
GROUP BY 
    so.name 
ORDER BY 
    5 DESC


Я поместил часть того, что я считаю правильным направлением того, что я пытаюсь достичь.

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

вот оригинал:

SELECT 
    [TableName] = so.name, 
    [RowCount] = MAX(si.rows) 
FROM 
    sysobjects so, 
    sysindexes si 
WHERE 
    so.xtype = 'U' 
    AND 
    si.id = OBJECT_ID(so.name) 
GROUP BY 
    so.name 
ORDER BY 
    2 DESC


в любом случае, я пытаюсь получить это с помощью нескольких дополнительных полей, я буду передавать значения через listview как sqldatareader, что сделает его представлением только для чтения. Я могу использовать оригинал, и он отлично работает, так как показывает только фактическое имя таблицы и максимальное количество строк.

Что я уже пробовал:

Я попытался переключить свойства с sys. columns на все столбцы и попытался установить только само имя CMA.name, CMI.name, и SCM.name

https://gyazo.com/f53f611cc9a9f6f2fd28c01de0e78ec9

Я приложил фотографию

OriginalGriff

Извините, но это не очень хороший вопрос - он даже близко не подходит к допустимому SQL. И ваше описание совсем не помогает - я понятия не имею из описания и кода, чего вы пытаетесь достичь.
Поэтому сделайте шаг назад и попытайтесь объяснить, какой вывод вы хотите получить, на примерах и помня, что мы не можем видеть ваш экран, получить доступ к вашему жесткому диску или прочитать ваши мысли.
Используйте виджет" улучшить вопрос", чтобы отредактировать свой вопрос и предоставить более подробную информацию.

CHill60

OriginalGriff не поймет, что вы пытались ответить, так как вы не использовали ссылку "ответить" рядом с его постом. Однако гиперссылка на самом деле не работает. Картина на самом деле тоже не помогает объяснить вашу проблему. Действительно трудно определить, в чем ваша проблема

Member 11856456

Я добавил дополнительную информацию к этому вопросу и формату о том, как он должен выглядеть.

Member 11856456

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

CHill60

Что такое год1 и год2?

Member 11856456

Год1 будет минимальным годом рождения год2 будет максимальным годом рождения. таким образом, при отображении он будет показывать минимальное значение в определенном столбце, а в другом, который является year2, он будет показывать максимальное значение в определенном столбце. поэтому буквально я показываю в таблице год самого старого и самого молодого человека в этой базе данных, что даст им диапазон.

CHill60

Ого! Вы, кажется, говорите, что у вас есть много баз данных со многими таблицами, содержащими данные о людях?

Member 11856456

вы правы, я думаю, что у меня есть около 10 баз данных, примерно 600 таблиц. Я просто пытаюсь получить информацию о каждом из них и вывести их на экран.

CHill60

Это не похоже на особенно хороший дизайн. Вероятно, вы уже знаете имена таблиц, содержащих нужные вам данные, и столбцов, в которых они хранятся? Вы действительно собираетесь добавлять новые таблицы с такой информацией? (Я не думаю, что вам нужно смотреть на системные таблицы).
Можете ли вы поделиться (кратким) обзором схемы?

Member 11856456

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

CHill60

Сколько человек вы храните на каждом столе. Кстати, иметь несколько таблиц абсолютно не быстрее.
Если вы знаете имена столбцов, которые содержат нужные вам данные, то вам нужно выдать MAX/MIN против этих имен столбцов - нет никакого способа, чтобы запрос системных таблиц сказал вам, какие столбцы содержат DOB.

Member 11856456

На данный момент у меня есть примерно 25 000 000 имен, связанных со всеми базами данных и таблицами

1 Ответов

Рейтинг:
0

CHill60

Хорошо. Я все еще думаю, что ваша установка странная, и мы изо всех сил пытаемся понять, что вы пытаетесь сделать, однако вот некоторые вещи, которые вы можете изменить в соответствии со своими собственными требованиями.

Я создаю промежуточную таблицу результатов:

if exists (select * from INFORMATION_SCHEMA.TABLES 
where TABLE_NAME = 'tempResults' AND TABLE_SCHEMA = 'dbo') drop table dbo.tempResults

create table tempResults
(
	id int identity(1,1),
	databasename varchar(128),
	schemaname varchar(128),
	tablename varchar(128),
	columnname varchar(1128),
	rowsintable int,
	system_type_id int,
	minvalue varchar(128),
	maxvalue varchar(128)
)
Обратите внимание на minvalue и maxvalue столбцы не могут быть определены из системных таблиц (что является частью проблемы с вашим подходом)

Я изначально заполнил эту таблицу каждым столбцом каждой таблицы каждой базы данных на моем сервере :
DECLARE @src NVARCHAR(MAX), @sql NVARCHAR(MAX);

SELECT @sql = N'', @src = N' UNION ALL 
SELECT ''$d'' as databasename, 
    s.name COLLATE SQL_Latin1_General_CP1_CI_AI as schemaname,
    t.name COLLATE SQL_Latin1_General_CP1_CI_AI as tablename,
	c.name COLLATE SQL_Latin1_General_CP1_CI_AI as columnname,
	i.rowcnt as rowsintable, c.system_type_id as system_type_id,
	cast(0 as varchar(128)) as minvalue, cast(0 as varchar(128)) as maxvalue
  FROM [$d].sys.schemas AS s
  INNER JOIN [$d].sys.tables AS t
  ON s.[schema_id] = t.[schema_id]
  INNER JOIN [$d].sys.all_columns as c ON c.object_id=t.object_id
  INNER JOIN [$d].sys.sysindexes i ON c.object_id = i.id
';

SELECT @sql = @sql + REPLACE(@src, '$d', name)
  FROM sys.databases
  WHERE database_id > 4
    AND [state] = 0
    AND HAS_DBACCESS(name) = 1;

SET @sql = STUFF(@sql, 1, 10, CHAR(13) + CHAR(10));
SET @sql = 'INSERT INTO tempresults SELECT * FROM (' + @sql + ') AS C '
--PRINT @sql;
EXEC sys.sp_executesql @sql;
Возможно, вы предпочтете (т. е. должны) ограничить это соглашением об именовании таблиц, которое вы используете для своих пользовательских таблиц, или именами столбцов, содержащих нужные вам данные.

Затем я обновляю эту таблицу, запрашивая фактические таблицы в самих базах данных:
declare @dbname varchar(max)
declare @scheme varchar(max)
declare @table varchar(max)
declare @column varchar(max)
declare @ccSql nvarchar(max)
declare @maxid int =(SELECT MAX(id) from tempresults)
declare @curid int = (SELECT MIN(id) from tempresults)

WHILE @curid <= @maxid
BEGIN
	SELECT @dbname = databasename, 
		@scheme = schemaname, 
		@table  = tablename, 
		@column = columnname 
	FROM tempresults TD 
	INNER JOIN sys.types T on TD.system_type_id = T.system_type_id
	WHERE id = @curid
	AND T.name NOT IN ('bit','image','text','ntext') -- and any others that can't be passed to MIN/MAX

	if @column IS NOT NULL 
	BEGIN
		SET @ccSql = 'UPDATE tempresults SET minvalue = B.the_min, maxvalue=B.the_max FROM ('
		SET @ccSql = @ccSql + 'SELECT MIN(['+@column+']) AS the_min, MAX([' + @column + ']) AS the_max FROM ['
		SET @ccSql = @ccSql + @dbname + '].[' + @scheme + '].[' +@table +']) B WHERE id=' + cast(@curid as varchar(128))

		--PRINT @ccSql
		EXEC sys.sp_executesql @ccsql;
	
	END
	SET @curid = @curid + 1

END
Пункты для рассмотрения:
1.Вам не нужно этого делать - с вашим дизайном явно что-то не так.
2. это занимает много времени, поэтому попробуйте отфильтровать его дальше
3.Возможно, вы захотите еще больше ограничить рассматриваемые столбцы просто включением даты, времени или целых чисел (я понятия не имею, откуда вы получаете год1 и год2) - это улучшит производительность запроса.
4.Вы можете получить или не получить некоторые предупреждения о нулевых значениях в агрегатных функциях (я их проигнорировал).

Я получаю результаты, похожие на следующие:
Northwind dbo Employees	EmployeeID	9	56	1	9
Northwind dbo Employees	LastName	9	231	Buchanan	Suyama
Northwind dbo Employees	FirstName	9	231	Andrew	Steven
Northwind dbo Employees	TitleOfCourtesy	9	231	Dr.	Ms.
Northwind dbo Employees	BirthDate	9	61	Sep 19 1937 12:00AM	Jan 27 1966 12:00AM
Northwind dbo Employees	HireDate	9	61	Apr  1 1992 12:00AM	Nov 15 1994 12:00AM
Northwind dbo Employees	Address	9	231	14 Garrett Hill	Edgeham Hollow
Winchester Way