문제

아래 쿼리를 더 읽기 쉬운 수정 가능한 것으로 리팩터링하려고합니다. 전반전은 쿼리 된 데이터베이스를 제외하고는 두 번째와 동일합니다 (테이블 이름은 동일합니다.)

  SELECT
    Column 1 AS c1,
    ...
    Column N AS cN
  FROM
    database1.dbo.Table1

UNION

  SELECT
    'Some String' as c1,
    ...
    NULL as cN
  FROM
    database1.dbo.Table2

UNION

  SELECT
    Column 1 AS c1,
    ...
    Column N AS cN
  FROM
    database2.dbo.Table1

UNION

  SELECT
    'Some String' as c1,
    ...
    NULL as cN
  FROM
    database2.dbo.Table2

이 쿼리는의 정의입니다 마른 그리고 저에게 다시 쓴 것을 부르지 만, 나는 방법을 전혀 모른다!

편집하다: 우리는 LINQ를 사용할 수 없으며 뚜렷한 결과를 원합니다. 결과가 반환되지 않고 물리적 파일 크기에서 쿼리를 더 작게 만들고자합니다.

편집하다: 쿼리하는 데이터베이스는 독점적 인 ERP 데이터베이스입니다. 구조 조정 옵션이 아닙니다.

도움이 되었습니까?

해결책

이것은 꽤 표준 SQL 패턴입니다. 때로는 건조와 같은 OOP/절차 코드 원칙을 SQL로 부주의하게 전송하기가 쉽지만 반드시 전송 가능한 개념은 아닙니다.

쿼리의 전체 논리적 디자인을 얼마나 쉽게 생각할 수 있는지, 서브 모듈을 통한 사냥. 하위 표현 중 하나에 여분의 열이 있거나 열이 반전되면 튀어 나옵니다. 이것은 기본적으로 실행 장치로서 Grok에게 매우 간단한 SQL 문으로, 그것을 분리하면 그것을 방해 할 것입니다.

디버깅 할 때 편집기의 텍스트 강조 표시 옵션을 사용하여 진술의 일부를 선택적으로 연습 할 수있어서 절차 코드에 존재하지 않는 기술입니다. Otoh, 그것은 시야에 흩어져있는 경우 모든 조각을 추적하려고 지저분해질 수 있습니다. CTE 조차도이 불편을 줄 수 있습니다.

다른 팁

나는 여기서 사지로 나가서 우리에게 준 정보를 바탕으로 말할 것입니다.

그것은 얻을만큼 좋은

박쥐에서 볼 수있는 한 가지 성능 팁은 사용 중입니다. UNION ALL 대신에 UNION 의도적으로 별개의 기록을 원하지 않는 한. 간단한 UNION 시간이 걸리는 중복을 제거합니다. UNION ALL 그렇게하지 않습니다.

동적 SQL과 루프로 다시 쓸 수 있지만 결과는 더 나빠질 것이라고 생각합니다. 동적 SQL 접근법을 정당화하기에 충분한 중복 코드가 있다면, 정당화 될 수 있다고 생각합니다.

또는 저장된 절차에서 논리를 LINQ와 같은 것으로 옮기는 것을 고려 했습니까? 많은 사람들에게 이것은 옵션이 아니므로 단지 묻습니다.

마지막 참고 사항 : 깨끗하게 보이도록 깨지지 않은 것을 고치려는 충동에 저항하십시오. 정리가 유지 보수, 확인 등을 보증하면 이동하면 이동하십시오.

뭐가 문제 야? 너무 오래? 너무 반복적입니까?

때때로 당신은 못생긴 SQL을 얻습니다.

별도의 견해를 사용하고 함께 통합하지 않으려면 정리할 수있는 방법이 없습니다.

나는 거의 오버 헤드가 거의없는 조회수에 투표합니다 (OK, 작은 컴파일 타임 비용이지만 모든 것이되어야합니다). 그런 다음 Procs는 형태가됩니다

SELECT * FROM database1.view1
UNION
SELECT * FROM database1.view2
UNION
SELECT * FROM database2.view1
UNION
SELECT * FROM database2.view2

나는 대부분의 플랫폼이 그것을 견딜 것으로 기대하지만 더 이상 압축하고 싶은지 확실하지 않습니다.

동적 SQL 테마에서 - 여기 샘플이 있습니다. 더 나은지 확실하지 않습니다. 이점은 선택 목록을 한 번만 작성하면됩니다.

DECLARE @Select1 varchar(1000)
DECLARE @Select2 varchar(1000)

DECLARE @SQL varchar(4000)


SET @Select1 = 'SELECT
    Column 1 AS c1,
    ...
    Column N AS cN'


SET @Select2 = 'SELECT
    ''Some String'' as c1,
    ...
    NULL as cN'


SET @SQL = @Select1 + ' FROM database1.dbo.Table1 '

SET @SQL = @SQL + ' UNION ' + @Select2 + ' FROM database1.dbo.Table2 '

SET @SQL = @SQL + ' UNION ' + @Select1 + ' FROM database2.dbo.Table1 '

SET @SQL = @SQL + ' UNION ' + @Select2 + ' FROM database2.dbo.Table2 '


EXEC @SQL

모든 Procs가 이것처럼 보이면 - 당신은 아마도 건축 문제가있을 것입니다.

Table2에 대한 모든 호출은 하나의 유용한 필드 만 있습니까? (그리고 노조 때문에 결국 단 하나의 행이 있습니까?)

나는이 작업에 대해 매개 변수화 된 동적 SQL 및/또는 코드 생성으로 가고 있다는 아이디어를 완전히 사용하는 것도 역동적으로 열 목록을 생성하는 것까지 INFORMATION_SCHEMA. 이것은 정확히 필요한 것이 아니지만 시작입니다 (데이터베이스 및 테이블 테이블을 생성 할 수 있음).

DECLARE @template AS varchar(MAX)
SET @template = 'SELECT {@column_list} FROM {@database_name}.dbo.{@table_name}'
DECLARE @column_list AS varchar(MAX)

SELECT @column_list = COALESCE(@column_list + ',', '') + COLUMN_NAME
FROM database1.dbo.INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = @table_name
ORDER BY ORDINAL_POSITION

DECLARE @sql AS varchar(MAX)
SET @sql = @template
SET @sql = REPLACE(@sql, '{@column_list}', @column_list)
SET @sql = REPLACE(@sql, '{@database_name}', @database_name)
SET @sql = REPLACE(@sql, '{@table_name}', @table_name)

반환 된 행의 수에 따라 주변의 선택된 쿼리와 함께 Select에서 Union을 모두 사용하는 것이 가장 좋습니다. 나는 전에 비슷한 문제를 보았고 두 가지 다른 스타일에 대한 다른 실행 계획을 가지고있었습니다.

SELECT DISTINCT subquery.c1, subquery.cN
FROM
(
SELECT Column 1 AS c1, Column N AS cN FROM database1.dbo.Table1
UNION ALL
SELECT 'Some String' as c1, NULL as cN FROM database1.dbo.Table2
UNION ALL
SELECT Column 1 AS c1, Column N AS cN FROM database2.dbo.Table1
UNION ALL
SELECT 'Some String' as c1, NULL as cN FROM database2.dbo.Table2
) subquery
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top