2017-12-07 171 views
5
Country Percentage 

India  12% 
USA  20% 
Australia 15% 
Qatar  10% 

wyjściowa:Jak podzielić tabelę SQL na pół i wysłać drugą połowę wierszy do nowych kolumn za pomocą zapytania SQL?

Country1 Percentage1  Country2  Percentage2 
India  12%    Australia 15% 
USA   20%    Qatar  10% 

Na przykład nie jest krajem, który ma stół procentowe, muszę podzielić tabelę na pół i pokazać drugą połowę (czyli pozostałych wierszach) w nowych kolumnach. Podałem także strukturę tabeli w tekście.

+4

Większość ludzi tutaj chce sformatowany tekst, a nie obrazy. – jarlh

+4

Skąd wiemy, która kolumna ma być używana w każdym kraju? – jarlh

+1

jarlh - Czy pytanie nie jest jasne za pośrednictwem obrazu? Kolejność, w jakiej kraje są obecne, tylko w tej kolejności musimy podzielić. Podobnie jak w - Indie i USA są pierwszym i drugim krajem, aw kolejnych kolumnach powinny znaleźć się następujące kraje. –

Odpowiedz

3

Spróbuj

declare @t table 
(
Country VARCHAR(20), 
percentage INT 
) 
declare @cnt int 

INSERT INTO @T 
VALUES('India',12),('USA',20),('Australia',15),('Quatar',12) 

select @cnt = count(1)+1 from @t 

;with cte 
as 
(
    select 
    SeqNo = row_number() over(order by Country), 
    Country, 
    percentage 
    from @t 
) 
select 
* 
from cte c1 
left join cte c2 
on c1.seqno = ([email protected]/2) 
and c2.SeqNo >= (@cnt/2) 
where c1.SeqNo <= (@cnt/2) 
+1

Nie działa, jeśli liczba wierszy jest nieparzysta. – Leran2002

+0

Wprowadziłem drobne zmiany w kodzie, sprawdź teraz –

+0

Ok. Teraz działa! – Leran2002

2

Moje wariant

SELECT 'A' Country,1 Percentage INTO #Country 
UNION ALL SELECT 'B' Country,2 Percentage 
UNION ALL SELECT 'C' Country,3 Percentage 
UNION ALL SELECT 'D' Country,4 Percentage 
UNION ALL SELECT 'E' Country,5 Percentage 

;WITH numCTE AS(
    SELECT 
    *, 
    ROW_NUMBER()OVER(ORDER BY Country) RowNum, 
    COUNT(*)OVER() CountOfCountry 
    FROM #Country 
), 
set1CTE AS(
    SELECT Country,Percentage,ROW_NUMBER()OVER(ORDER BY Country) RowNum 
    FROM numCTE 
    WHERE RowNum<=CEILING(CountOfCountry/2.) 
), 
set2CTE AS(
    SELECT Country,Percentage,ROW_NUMBER()OVER(ORDER BY Country) RowNum 
    FROM numCTE 
    WHERE RowNum>CEILING(CountOfCountry/2.) 
) 
SELECT 
    s1.Country,s1.Percentage, 
    s2.Country,s2.Percentage 
FROM set1CTE s1 
LEFT JOIN set2CTE s2 ON s1.RowNum=s2.RowNum 

DROP TABLE #Country 
5

Po pierwsze, tego typu działania powinny być wykonywane w warstwie aplikacji, a nie w bazie danych. Powiedział, że może być interesującym ćwiczeniem, aby zobaczyć, jak to zrobić w bazie danych.

Użyłbym agregacji warunkowej lub pivot. Zauważ, że tabele SQL są z natury nieuporządkowane. Twoja tabela podstawowa nie ma widocznej kolejności, więc wartości mogą pojawić się w dowolnej kolejności.

select max(case when seqnum % 2 = 0 then country end) as country_1, 
     max(case when seqnum % 2 = 0 then percentage end) as percentage_1, 
     max(case when seqnum % 2 = 1 then country end) as country_2, 
     max(case when seqnum % 2 = 1 then percentage end) as percentage_2  
from (select c.*, 
      (row_number() over (order by (select null)) - 1) as seqnum 
     from country c 
    ) c 
group by seqnum/2; 
+0

Dzięki za rozwiązanie. Ale jedyny problem z tym związany polega na tym, że sekwencja się zmienia ... tzn. "USA" pojawia się w trzeciej kolumnie - "konto 2", zamiast tego, że powinna się znaleźć w "kraju 1", drugim rzędzie. Mam nadzieję, że masz to, co mam na myśli. W przeciwnym razie rozwiązanie jest solidne jak skała. Sprawdź, czy możesz podać rozwiązanie tego problemu. Dzięki jeszcze raz. –

+0

@ Nayan_07. . . Potrzebujesz sposobu na określenie kolejności. To idzie tam, gdzie '' (wybierz zero) 'idzie. Nie widzę żadnego naturalnego sposobu zamawiania twoich wierszy, chociaż możesz umieścić w jawnym 'order by', który sprawdza każdą wartość. –

1

Chciałem tylko spróbować czegoś. Użyłem funkcji OFFSET. To nie wymóg myślę dla przykładowych danych, ale nie wiem, czy jego kuloodpornej całą drogę:

kod SQL

declare @myt table (country nvarchar(50),percentage int) 
insert into @myt 
values 
('India'  ,12), 
('USA'  ,20), 
('Australia' ,15), 
('Qatar'  ,10), 
('Denmark',10) 



DECLARE @TotalRows int  
SET @TotalRows = (select CEILING(count(*)/2.) from @myt); 

WITH dataset1 AS (
SELECT *,ROW_NUMBER() over(order by country) as rn from (
SELECT Country,percentage from @myt a 
ORDER BY country OFFSET 0 rows FETCH FIRST @TotalRows ROWS ONLY 
) z 
) 

,dataset2 AS (
SELECT *,ROW_NUMBER() over(order by country) as rn from (
SELECT Country,percentage from @myt a  
ORDER BY country OFFSET @TotalRows rows FETCH NEXT @TotalRows ROWS ONLY 
) z 
) 

SELECT * FROM dataset1 a LEFT JOIN dataset2 b ON a.rn = b.rn 

Wynik

enter image description here

0

zakładając chcą zstępować alfabetyczne nazwy krajów, ale lewa kolumna jest określana przez lokalizację w wynikach: Indie:

with CoutryCTE as (
     select c.* 
      , row_number() over (order by country)-1 as rn 
     from country c 
    ) 
, Col as (
    select rn % 2 as num from CoutryCTE 
    where Country = 'India' 
    ) 
select max(case when rn % 2 = Col.num then country end) as country_1 
    , max(case when rn % 2 = Col.num then percentage end) as percentage_1 
    , max(case when rn % 2 <> Col.num then country end) as country_2 
    , max(case when rn % 2 <> Col.num then percentage end) as percentage_2  
from CoutryCTE 
cross join Col 
group by rn/2 
; 

SQLFiddle Demo

| country_1 | percentage_1 | country_2 | percentage_2 | 
|-----------|--------------|-----------|--------------| 
|  India |   12% | Australia |   15% | 
|  USA |   20% |  Qatar |   10% | 

nb: to jest niezwykle podobny do wcześniejszej odpowiedzi Gordon Linoff