In the Telerik Report Designer, how do you create a multi-column table with group headers? - sql

I'm using the Telerik Report Designer (the standalone application, not the one in Visual Studio). I have a dataset with two fields: group and task. I'd like to make a table where each group is in it's own column with the tasks for that group listed below. The best I've come up with is a crosstab report that shows the groups and tasks and their counts, but this isn't what the client wants. How can I get the results I want in the report designer? If Telerik controls can't do this, how could I rewrite my SQL query to output the data is the format I want so I can directly use the SQL output to populate a table?
Here is my dataset:
The query I used to get that dataset is:
SELECT
tblDtl.Group
, tblDtl.Task
FROM tblHdr
INNER JOIN tblDtl ON tblHdr.CLHId = tblDtl.CLHId
INNER JOIN tblType ON tblHdr.CLHId = tblType.SelectedId
INNER JOIN tblOrder ON tblType.TypeId = tblOrder.Type
ORDER BY tblDtl.CLDDisplayOrder
Here is my desired output:
The best I've gotten is a crosstab that looks like this:

* Partial Answer *
I wasn't able to figure out how to get the 2 columns I wanted, but I used the code below to at least get the header in the first row with the details below it. I put this code in a stored procedure and then used that stored procedure as the data source for a table within the Telerik report.
CREATE TABLE #Checklist
(
Checklist varchar(200),
Notes varchar(50)
)
SET NOCOUNT ON;
DECLARE
#HeaderName varchar(200),
#GroupName varchar(200),
#TaskGroupName varchar(200),
#TaskDesc nvarchar(200)
DECLARE header_cursor CURSOR FOR
SELECT DISTINCT tblCheckListHdr.CLHName, tblCheckListDtl.CLDGroupName
FROM tblCheckListHdr
INNER JOIN tblCheckListDtl ON tblCheckListHdr.CLHId = tblCheckListDtl.CLHId
INNER JOIN tblServiceType ON tblCheckListHdr.CLHId = tblServiceType.SelectedCLHId
INNER JOIN tblWorkOrder ON tblServiceType.ServiceTypeId = tblWorkOrder.ServiceType
WHERE tblWorkOrder.WorkOrderId = #WOid
AND tblCheckListHdr.CLHActive = 1
ORDER BY tblCheckListDtl.CLDGroupName
OPEN header_cursor
FETCH NEXT FROM header_cursor INTO #HeaderName, #GroupName
WHILE ##FETCH_STATUS = 0
BEGIN
INSERT INTO #Checklist (Checklist, Notes)
SELECT #HeaderName + ' | ' + #GroupName, 'Y, N, NA, Notes' AS Notes
DECLARE detail_cursor CURSOR FOR
SELECT tblCheckListDtl.CLDGroupName
, tblCheckListDtl.CLDTaskDesc
FROM tblCheckListHdr
INNER JOIN tblCheckListDtl ON tblCheckListHdr.CLHId = tblCheckListDtl.CLHId
INNER JOIN tblServiceType ON tblCheckListHdr.CLHId = tblServiceType.SelectedCLHId
INNER JOIN tblWorkOrder ON tblServiceType.ServiceTypeId = tblWorkOrder.ServiceType
WHERE tblWorkOrder.WorkOrderId = #WOid
AND tblCheckListHdr.CLHActive = 1
AND tblCheckListDtl.CLDActive = 1
AND tblCheckListDtl.CLDGroupName = #GroupName
ORDER BY tblCheckListDtl.CLDDisplayOrder
OPEN detail_cursor
FETCH NEXT FROM detail_cursor INTO #TaskGroupName, #TaskDesc
WHILE ##FETCH_STATUS = 0
BEGIN
INSERT INTO #Checklist (Checklist)
SELECT #TaskDesc
FETCH NEXT FROM detail_cursor INTO #TaskGroupName, #TaskDesc
END
CLOSE detail_cursor
DEALLOCATE detail_cursor
FETCH NEXT FROM header_cursor INTO #HeaderName, #GroupName
END
CLOSE header_cursor;
DEALLOCATE header_cursor
SELECT #Checklist.Checklist, #Checklist.Notes
FROM #Checklist

this can be achieve using PIVOT, Something like this.
IF ( OBJECT_ID('tempdb..#tmpDB') IS NOT NULL )
BEGIN
DROP TABLE #tmpDB
END
SELECT testing ,
production
INTO #tmpDB
FROM (
SELECT
tblDtl.GROUP [group]
, tblDtl.Task [task]
FROM tblHdr
INNER JOIN tblDtl ON tblHdr.CLHId = tblDtl.CLHId
INNER JOIN tblType ON tblHdr.CLHId = tblType.SelectedId
INNER JOIN tblOrder ON tblType.TypeId = tblOrder.Type
ORDER BY tblDtl.CLDDisplayOrder
) P PIVOT ( MAX(task) FOR [group] IN ( testing, production ) ) PVT;
WITH CTEtesting
AS ( SELECT ROW_NUMBER() OVER ( ORDER BY testing ) ctr ,
testing
FROM #tmpDB
WHERE production IS NULL
),
CTEProduction
AS ( SELECT ROW_NUMBER() OVER ( ORDER BY production ) ctr ,
production
FROM #tmpDB
WHERE testing IS NULL
),
CTE
AS ( SELECT testing ,
production
FROM CTEProduction P
FULL JOIN CTEtesting T ON T.ctr = P.ctr
)
SELECT *
FROM CTE
Result:
testing production
-------------------- --------------------
Add object Prompt for input
Report object Show error log
Show error log Show report
Vaidate object Validate input
Validate report Validate object
Vanipulate object NULL
(6 row(s) affected)

Related

SQL Server stored procedure breaking up results

I am trying to get a list back from a stored procedure, but I believe I may have used the wrong method?
The data I am getting back is fine, but is breaking up the results into sections instead of one continuous result.
I need it to be in one continuous result as it needs to be then exported out to an accounting program.
UPDATE
I maybe should have mentioned I am teaching myself SQL and procedures, so I don't entirely know what I am doing, so please forgive me. :)
I spent most of last week writing and re-writing before finally coming here to ask for help.
What I had written was overly complicated I now realise (not to mention not giving the response the way I needed.) I was trying to repurpose code I had found elsewhere.
This is my corrected code.
#varBillingDealerPeriodID int
AS
DECLARE #BillingDealerBatchRosterID int;
BEGIN TRY
SELECT count( * ) AS ItemTotalCount
, di.DealerName
, di.DealerID
, bdbr.BillingDateTo
, bdinr.BillingDealerInvoiceNumber
FROM dbo.billing_dealer_batch_item bdbi
LEFT JOIN dbo.dealer_info di ON di.DealerID = bdbi.DealerID
LEFT JOIN dbo.billing_dealer_batch_roster bdbr ON bdbr.BillingDealerBatchRosterID = bdbi.BillingDealerBatchRosterID
LEFT JOIN dbo.billing_dealer_invoice_number_roster bdinr ON bdinr.DealerID = di.DealerID
WHERE bdbi.BillingDealerBatchRosterID IN (
SELECT DISTINCT BillingDealerBatchRosterID
FROM dbo.billing_dealer_batch_roster
WHERE BillingDealerPeriodID = #varBillingDealerPeriodID
)
AND bdbi.ItemConditionID < 2
GROUP BY di.DealerName
, di.DealerID
, bdbr.BillingDateTo
, bdinr.BillingDealerInvoiceNumber
END TRY
Thank you for everyone's help!
Get rid of the cursor and the loop.
Then change this
AND bdbi.BillingDealerBatchRosterID = #BillingDealerBatchRosterID
To this
AND bdbi.BillingDealerBatchRosterID IN (
SELECT DISTINCT BillingDealerBatchRosterID
FROM dbo.billing_dealer_batch_roster
WHERE BillingDealerPeriodID = #varBillingDealerPeriodID
)
By using the cursor you can just use the following codes. Here, you may need to change the data type for the temp table as per your need.
CREATE PROCEDURE [dbo].[billing_generate_invoice]
#varBillingDealerPeriodID int
AS
BEGIN
IF OBJECT_ID('tempdb..##tmp_billing_generate_invoice', 'U') IS NOT NULL
BEGIN
DROP TABLE ##tmp_billing_generate_invoice
END
CREATE TABLE ##tmp_billing_generate_invoice
(
ItemTotalCount INT,
BillingDealerBatchRosterID INT,
DealerName VARCHAR(500),
ServiceLevelID INT,
FreshItemFeeID INT,
WebsiteFeeID INT,
WebsiteBillingFrequencyID INT,
BillingDateTo DATE,
BillingDealerInvoiceNumber VARCHAR(500)
)
DECLARE #BillingDealerBatchRosterID int;
DECLARE MyCursor CURSOR LOCAL FOR
SELECT BillingDealerBatchRosterID
FROM dbo.billing_dealer_batch_roster
WHERE BillingDealerPeriodID = #varBillingDealerPeriodID;
OPEN MyCursor;
FETCH NEXT FROM MyCursor INTO #BillingDealerBatchRosterID;
WHILE ##fetch_status = 0
BEGIN
-- START
INSERT INTO ##tmp_billing_generate_invoice(
ItemTotalCount,
BillingDealerBatchRosterID,
DealerName,
ServiceLevelID,
FreshItemFeeID,
WebsiteFeeID,
WebsiteBillingFrequencyID,
BillingDateTo,
BillingDealerInvoiceNumber
)
SELECT
COUNT(*) AS ItemTotalCount,
bdbr.BillingDealerBatchRosterID,
di.DealerName,
-- di.DealerID
da.ServiceLevelID,
da.FreshItemFeeID,
da.WebsiteFeeID,
da.WebsiteBillingFrequencyID,
bdbr.BillingDateTo,
bdinr.BillingDealerInvoiceNumber
FROM
dbo.billing_dealer_batch_item bdbi
LEFT JOIN
dbo.dealer_info di ON di.DealerID = bdbi.DealerID
LEFT JOIN
dbo.dealer_account da ON da.DealerID = di.DealerID
LEFT JOIN
dbo.billing_dealer_batch_roster bdbr ON bdbr.BillingDealerBatchRosterID = bdbi.BillingDealerBatchRosterID
INNER JOIN
dbo.billing_dealer_invoice_number_roster bdinr ON bdinr.DealerID = di.DealerID
-- LEFT JOIN dbo.lookup__rate_weekly_fee_LR lrwf ON lrwf.ItemQuantity = ItemTotalCount
-- LEFT OUTER JOIN dbo.billing_dealer_batch bdb ON bdb.DealerID = di.DealerID
WHERE
bdbi.DealerID IN (SELECT DISTINCT DealerID
FROM dbo.billing_dealer_batch
WHERE DealerID = bdbi.DealerID
AND BillingDealerBatchRosterID = #BillingDealerBatchRosterID
AND DealerAccountStatusID = 4 -- Dealer Status 4 is ACTIVE only
)
AND bdbi.BillingDealerBatchRosterID = #BillingDealerBatchRosterID -- Roster Week
AND bdbi.ItemConditionID < 2 -- Less than 2 is AS-IS and Used
GROUP BY
bdinr.BillingDealerInvoiceNumber,
bdbi.DealerID,
di.DealerName,
-- di.DealerID
bdbr.BillingDateTo,
da.ServiceLevelID,
da.FreshItemFeeID,
da.WebsiteFeeID,
da.WebsiteBillingFrequencyID,
bdbr.BillingDealerBatchRosterID
ORDER BY
bdinr.BillingDealerInvoiceNumber;
-- END
FETCH NEXT FROM MyCursor INTO #BillingDealerBatchRosterID;
END;
CLOSE MyCursor;
DEALLOCATE MyCursor;
SELECT * FROM ##tmp_billing_generate_invoice
END

How to join data from the same table and same column to two different columns

LN_REF_NO is the reference number of the loan. LN_REF_NO must have one ACNO AND ONE LRAC.
BOTH OF THEM ARE STORED TO ACCOUNTS UNDER ACNO COLUMN.
HOW I WILL SEPARATE THEM ? PLS LOOK THE IMAGE
ALTER PROCEDURE sp_FinalLoanPayment
AS
DECLARE #LN_REF_NO char(13)
DECLARE #TempA
TABLE (
[LN_REF_NO] [char](13),
[Status] [varchar](15),
[ACNO] [varchar](21),
[ACNOBalance] [dbo].[Amount]
)
DECLARE #TempL
TABLE (
[LN_REF_NO] [char](13),
[Status] [varchar](15),
[LRAC] [varchar](21),
[LRACBalance] [dbo].[Amount]
)
DECLARE #TempAll
TABLE (
[LN_REF_NO] [char](13),
[Status] [varchar](15),
[ACNO] [varchar](21),
[ACNOBalance] [dbo].[Amount],
[LRAC] [varchar](21),
[LRACBalance] [dbo].[Amount]
)
INSERT INTO #TempL (LN_REF_NO ,Status,LRAC,LRACBalance)
SELECT Loan.LN_REF_NO, Loan.Status,ACCOUNTS.ACNO ,ACCOUNTS.BALANCE
FROM Loan
INNER JOIN Accounts
ON LOAN.LRAC = ACCOUNTS.ACNO
WHERE Loan.Status ='Paid' AND ACCOUNTS.BALANCE>0
INSERT INTO #TempA (LN_REF_NO ,Status,ACNO,ACNOBalance)
SELECT Loan.LN_REF_NO, Loan.Status,ACCOUNTS.ACNO ,ACCOUNTS.BALANCE
FROM Loan
INNER JOIN Accounts
ON LOAN.ACNO = ACCOUNTS.ACNO
WHERE Loan.Status ='Paid' AND ACCOUNTS.BALANCE<0
-- START CURSOR 1
DECLARE #cursor CURSOR
SET #cursor = CURSOR FOR
select LN_REF_NO from #TempL
OPEN #cursor
FETCH NEXT
FROM #cursor INTO
#LN_REF_NO
WHILE (##FETCH_STATUS = 0)
BEGIN
INSERT INTO #TempAll (LN_REF_NO ,Status,ACNO,ACNOBalance)
select LN_REF_NO,Status,ACNO,ACNOBalance
from #TempA
where LN_REF_NO = #LN_REF_NO
FETCH NEXT
FROM #cursor INTO
#LN_REF_NO
END
CLOSE #cursor
DEALLOCATE #cursor
-- CURSOR 1 END
select * from #TempAll order by LN_REF_NO
Results:
I think you should be able to get this data as you need it with this query:
SELECT
ln.LN_REF_NO, ln.Status, a1.ACNO, a1.BALANCE, a2.ACNO, a2.BALANCE
FROM
dbo.Loan ln
INNER JOIN
dbo.Accounts a1 ON ln.LRAC = a1.ACNO
INNER JOIN
dbo.Accounts a2 ON ln.ACNO = a2.ACNO
WHERE
ln.Status = 'Paid'
AND a1.Balance > 0
AND a2.Balance > 0
You basically just join to the Accounts table twice - once for the link to Loan.LRAC and a second time for the link on Loan.ACNO.
Based on those two joins, you just pick those columns from all joined tables that you need - and that's really all there is! No cursor, no temp tables - nothing like that needed !

optimizing the code

I have written this code for small database but know the database size has increased,it is showing timeout error.plz help in optimizing it
Below is the code:-
IF OBJECT_ID('Temp_expo') is not null
begin
drop table Temp_expo
end
set #query3 = 'SELECT SPCT_ID_REL_LOW,SPCT_ID_REL_HIGH,ROW_NUMBER() over (order by PDBC_PFX) as TempId
INTO Temp_expo
FROM ['+ #FCTServer +'].['+#FCTDBName+'].dbo.CMC_SPCT_SUPP_CONV
where SPCT_ID_REL_LOW <> '''' and SPCT_ID_REL_HIGH <> '''''
exec (#query3)
Select #minCount= min(TempId) from Temp_expo
Select #maxCount= max(TempId) from Temp_expo
create table #ICD9SPCT
(
ICD9Code varchar(200)
}
while #minCount<=#maxCount
begin
select #low=SPCT_ID_REL_LOW,#high=SPCT_ID_REL_HIGH
from Temp_expo
where TempId=#minCount
group by SPCT_ID_REL_LOW,SPCT_ID_REL_HIGH
set #loworder = (select ISNULL(OrderId,0) from FCT_ICD9_Diag_ORDER where ICD9=#low)
set #highorder = (select ISNULL(OrderId,0) from FCT_ICD9_Diag_ORDER where ICD9=#high)
insert into #ICD9SPCT
select ICD9 from FCT_ICD9_Diag_ORDER ordert
left join #ICD9SPCT icdorder on ordert.ICD9 = icdorder.ICD9Code
where OrderId between #loworder and #highorder and icdorder.ICD9Code is null
set #minCount = #minCount+1;
end
If this is for SQL SERVER, there are some basic tips you can try:
USE: WITH (NOLOCK) after every select you use.
i.e.
select ICD9 from FCT_ICD9_Diag_ORDER ordert WITH (NOLOCK)
left join #ICD9SPCT icdorder on ordert.ICD9 = icdorder.ICD9Code
where OrderId between #loworder and #highorder and icdorder.ICD9Code is null
You can also try to change your temp tables to variable tables, by just changing the # for an # like :
create table #ICD9SPCT
(
ICD9Code varchar(200)
}
Still, the WHILE loop you are using may be the primary cause of your problem.

insert value from one table to another checking id

I have 2 tables.All the ids are include in table one (Tbl_Distributor). 2nd table have all the names.
I want to add all the names to first table according to id.
My select query as below.
INSERT INTO dbo.Tbl_Distributor(Giv_Name) where dealercode= a.dealercode
SELECT a.dealercode,d.nameinfull
FROM dealerplacement a,dealer d
where a.dealercode= d.dealercode
order by a.dealercode ASC
This returns nameinfull and dealercode. I want to add this nameinfull to Tbl_Distributor .
Please help me to solve this issue.
UPDATE R
SET Giv_Name = D.FirstName
FROM
dbo.Tbl_Distributor R
INNER JOIN dbo.Dealer D
ON R.Dis_ID = D.DealerCode
You cannot use INSERT here. You need to use update. I'd do such a task using cursors.
declare #id int, #name varchar(1000)
DECLARE c CURSOR FOR
SELECT a.dealercode,d.nameinfull
FROM dealerplacement a,dealer d
where a.dealercode= d.dealercode
order by a.dealercode ASC
OPEN c
FETCH NEXT FROM c
INTO #id, #name
WHILE ##FETCH_STATUS = 0
BEGIN
update Tbl_Distributor set Giv_Name = #name where dealercode = #id
FETCH NEXT FROM c
INTO #id, #name
end
CLOSE c;
DEALLOCATE c;
Also, I'd use join in the select statement:
SELECT a.dealercode,d.nameinfull
FROM dealerplacement a inner join dealer d
on a.dealercode= d.dealercode
order by a.dealercode ASC

How to update a column fetched by a cursor in TSQL

Before I go any further: Yes, I know that cursors perform poorly compared with set-based operations. In this particular case I'm running a cursor on a temporary table of 100 or so records, and that temporary table will always be fairly small, so performance is less crucial than flexibility.
My difficulty is that I'm having trouble finding an example of how to update a column fetched by a cursor. Previously when I've used cursors I've retrieved values into variables, then run an update query at each step based upon these values. On this occasion I want to update a field in the temporary table, yet I can't figure out how to do it.
In the example below, I'm trying to update the field CurrentPOs in temporary table #t1, based upon a query that uses #t1.Product_ID to look up the required value. You will see in the code that I have attempted to use the notation curPO.Product_ID to reference this, but it doesn't work. I have also attempted to use an update statement against curPO, also unsuccessfully.
I can make the code work by fetching to variables, but I'd like to know how to update the field directly.
I think I'm probably missing something obvious, but can anyone help?
declare curPO cursor
for select Product_ID, CurrentPOs from #t1
for update of CurrentPOs
open curPO
fetch next from curPO
while ##fetch_status = 0
begin
select OrderQuantity = <calculation>,
ReceiveQuantity = <calculation>
into #POs
from PurchaseOrderLine POL
inner join SupplierAddress SA ON POL.Supplier_ID = SA.Supplier_ID
inner join PurchaseOrderHeader POH ON POH.PurchaseOrder_ID = POL.PurchaseOrder_ID
where Product_ID = curPO.Product_ID
and SA.AddressType = '1801'
update curPO set CurrentPOs = (select sum(OrderQuantity) - sum(ReceiveQuantity) from #POs)
drop table #POs
fetch next from curPO
end
close curPO
deallocate curPO
After doing a bit more googling, I found a partial solution. The update code is as follows:
UPDATE #T1
SET CURRENTPOS = (SELECT SUM(ORDERQUANTITY) - SUM(RECEIVEQUANTITY)
FROM #POS)
WHERE CURRENT OF CURPO
I still had to use FETCH INTO, however, to retrieve #t1.Product_ID and run the query that produces #POs, so I'd still like to know if it's possible to use FETCH on it's own.
Is this what you want?
declare curPO cursor
for select Product_ID, CurrentPOs from #t1
for update of CurrentPOs
open curPO
fetch next from curPO
while ##fetch_status = 0
begin
update curPO set CurrentPOs =
(select sum(<OrderQuantityCalculation>)
from PurchaseOrderLine POL
inner join SupplierAddress SA ON POL.Supplier_ID = SA.Supplier_ID
inner join PurchaseOrderHeader POH ON POH.PurchaseOrder_ID = POL.PurchaseOrder_ID
where Product_ID = curPO.Product_ID
and SA.AddressType = '1801') -
(select sum(<ReceiveQuantityCalculation>)
from PurchaseOrderLine POL
inner join SupplierAddress SA ON POL.Supplier_ID = SA.Supplier_ID
inner join PurchaseOrderHeader POH ON POH.PurchaseOrder_ID = POL.PurchaseOrder_ID
where Product_ID = curPO.Product_ID
and SA.AddressType = '1801')
fetch next from curPO
end
close curPO
deallocate curPO
Maybe you need something like that:
update DataBaseName..TableName
set ColumnName = value
where current of your_cursor_name;
Here's an example to calculate one column based upon values from two others (note, this could be done during the original table select). This example can be copy / pasted into an SSMS query window to be run without the need for any editing.
DECLARE #cust_id INT = 2, #dynamic_val NVARCHAR(40), #val_a INT, #val_b INT
DECLARE #tbl_invoice table(Cust_ID INT, Cust_Fees INT, Cust_Tax INT)
INSERT #tbl_invoice ( Cust_ID, Cust_Fees, Cust_Tax ) SELECT 1, 111, 11
INSERT #tbl_invoice ( Cust_ID, Cust_Fees, Cust_Tax ) SELECT 2, 222, 22
INSERT #tbl_invoice ( Cust_ID, Cust_Fees, Cust_Tax ) SELECT 3, 333, 33
DECLARE #TblCust TABLE
(
Rec_ID INT
, Val_A INT
, Val_B INT
, Dynamic_Val NVARCHAR(40)
, PRIMARY KEY NONCLUSTERED (Rec_ID)
)
INSERT #TblCust(Rec_ID, Val_A, Val_B, Dynamic_Val)
SELECT Rec_ID = Cust_ID, Val_A = Cust_Fees, Val_B = Cust_Tax, NULL
FROM #tbl_invoice
DECLARE cursor_cust CURSOR FOR
SELECT Rec_ID, Val_A, Val_B, Dynamic_Val
FROM #TblCust
WHERE Rec_ID <> #cust_id
FOR UPDATE OF Dynamic_Val;
OPEN cursor_cust;
FETCH NEXT FROM cursor_cust INTO #cust_id, #val_a, #val_b, #dynamic_val;
WHILE ##FETCH_STATUS = 0
BEGIN
UPDATE #TblCust
SET Dynamic_Val = N'#c = "' + LTRIM(STR((#val_a + #val_b), 40)) + N'"'
WHERE CURRENT OF cursor_cust
FETCH NEXT FROM cursor_cust INTO #cust_id, #val_a, #val_b, #dynamic_val;
END
CLOSE cursor_cust
DEALLOCATE cursor_cust
SELECT * FROM #TblCust