PDA

View Full Version : خروجی به شکل سطری



behrouzlo
چهارشنبه 21 مهر 1389, 16:41 عصر
تصور کنید من جدولی با ساختار پایین داریم و داده های زیر به آن اضافه شده است.


CREATE TABLE Tbl( GroupId INT NOT NULL,UserName NVARCHAR(50) )

INSERT INTO Tbl VALUES(1,'User1')
INSERT INTO Tbl VALUES(1,'User2')
INSERT INTO Tbl VALUES(1,'User3')

INSERT INTO Tbl VALUES(2,'User4')
INSERT INTO Tbl VALUES(2,'User5')
INSERT INTO Tbl VALUES(2,'User6')

حالا من می خواهم گزارشی را به شکل زیر از داده های وارد شده استخراج کنم


1,Use1 / User2 / User3
2,Use4 / User5 / User6
تعداد User های که در یک گروه قرار می گیرند محدودیت ندارد و استفاده از Cursor مجاز نیست. دوستان می توانند یک راه حل کارا برای این مسئله پیشنهاد کنند؟

s.Jabbari
چهارشنبه 21 مهر 1389, 21:05 عصر
اختمالا مقاله زیر بتوخ کمکتون کنه
http://www.30sharp.com/article/13/207/11/%d8%a8%d8%b1%d8%b1%d8%b3%db%8c-%da%af%d8%b2%d8%a7%d8%b1%d8%b4-%d8%a2%d9%85%d8%a7%d8%b1%db%8c-crosstab-%d8%a8%d8%ae%d8%b4-%d8%a7%d9%88%d9%84.aspx

بهزادصادقی
پنج شنبه 22 مهر 1389, 19:55 عصر
این چطوره؟



if object_id('dbo.Behrouzlo') is not null
drop function dbo.Behrouzlo;
go

create function dbo.Behrouzlo
(
@GroupID int
) returns nvarchar(max)
as
begin

declare @result nvarchar(max);

set @result =
(
select
t2.UserName + '/*'
from
Tbl t2
where
t2.GroupID = @GroupID
for xml path('')
);

set @result = @result + '*';
set @result = replace( @result, '/**', '' );
set @result = replace( @result, '/*', ' / ' );

return @result;

end;
go

select
ltrim( str( x.GroupID ) ) + ', ' + dbo.Behrouzlo( x.GroupID )
from
(
select distinct t1.GroupID from Tbl t1
) x;

behrouzlo
شنبه 24 مهر 1389, 10:15 صبح
آقای صادقی تشکر بابت پاسختان. ولی این روشی است که دقیقا من الان به کار بردم. ولی متاسفانه فقط تعداد رکوردها زیاد می شوند زمانی زیادی برای اجرا صرف می شود. حتی من با Cursor تست کردم زمان اجرا برای آن از این روش بهتر بود. آیا روش دیگری در نظر ندارید؟

بهزادصادقی
شنبه 24 مهر 1389, 19:10 عصر
آقای صادقی تشکر بابت پاسختان. ولی این روشی است که دقیقا من الان به کار بردم. ولی متاسفانه فقط تعداد رکوردها زیاد می شوند زمانی زیادی برای اجرا صرف می شود. حتی من با Cursor تست کردم زمان اجرا برای آن از این روش بهتر بود. آیا روش دیگری در نظر ندارید؟

آه. شاید اشکال از یک جای دیگر باشد. می شود کدی را که این تابع را فراخوانی می کند اینجا درج کنید؟

m_omrani
چهارشنبه 28 مهر 1389, 23:12 عصر
از تابع STUFF در يک GROUP BY استفاده کنيد. اين طوري:


SELECT r2.RoleID,r2.Title,STUFF
(
(
SELECT ', ' + TheUser FROM
(
SELECT r.RoleID, u.Username AS TheUser
FROM [Role] r
INNER JOIN [User_Role] ur ON ur.RoleID = r.RoleID
INNER JOIN [User] u ON ur.UserID = u.UserID
) r1
WHERE r2.RoleID = r1.RoleID FOR XML PATH('')
),1,1,''
) AS Users
FROM [Role] r2
GROUP BY r2.RoleID,r2.Titleتوضيح:

فرض کنيد در ديتابيس سه جدول داريم:

Role: نقش ها (شامل ستون هاي RoleID، Title و غيره)
User: کاربران (شامل ستون هاي UserID، Username, Password و غيره)
User_Role: نقش هاي کاربران (شامل ستون هاي UserID و RoleID)

حالا مي خواهيم پرس و جويي بنويسيم که مثلاً در صفحه مديريت نقش ها، در سطرهاي گريدي که هر نقش نمايش داده مي شه علاوه بر نمايش عنوان هر نقش، ليست کاربران اون نقش رو به صورت جدا شده با کاما، در ستون بعدي هم داشته باشيم.

مثلاً اين طوري:

+-----------+-------------------+
| Role | Users |
+-----------+-------------------+
| R1 | Ali, Reza, Hamid |
| R2 | Saeed, Kazem |
| ... | ... |
+-----------+-------------------+

البته يه چيزي رو هم اضافه کنم.
اگه تعداد رکوردهايي که مي خواد به هم بچسبه خيلي زياد باشه، (مثلاً در مثالي که من کُدش رو نوشتم تعداد کاربراني که يک نقش را دارند زياد باشند) بهتره از TOP براي کم کردن تعداد اونها استفاده کنيد. چون به هم چسبوندن همه اونها طول مي کشه لذا اجراي پرس و جو رو کُند مي کنه. اين روش زماني خيلي خوب جواب مي ده که به ازاي هر رکورد، تعداد رکوردهاي وابسته يا فرزندش کم باشه.