SQL Server Count Occurrences of a value of colounns - asp.net

Thank you for taking time to read this.
I have a ServiceDetails Table which have columns like
ID, ServiceID , ClientID... , Status ,IsFollowUp
and Services have
ID, Date , CityID, AreaID
Now when a service request is entered , its status is either 'pending', 'Completed','testing', or 'indeteriminent'.
Now end user wants a report that
City, Area , TotalServices , Total Completed without followup , Total Completed at First followup, Total Completed at 2nd followup ... , Total Completed at Fifth followup
I have Completed uptill now, Total Completed without followup but how do I calculate the Completed services followups count.
CREATE TABLE #TEMP#(
[ID] int PRIMARY KEY IDENTITY,
[Area] varchar(250),
[City] varchar(250),
[Total] int,
[WithoutFollowup] int,
[FirstFollowup] int,
[SecondFollowup] int,
[ThirdFollowup] int,
[FourthFollowup] int,
[FifthFollowup] int
);
DECLARE #AreaID AS bigint = 0
DECLARE #CityID AS bigint = 0
DECLARE #AreaName AS nvarchar(250) = ''
DECLARE #CityName AS nvarchar(250) = ''
DECLARE #VCCTDetailsID AS bigint = NULL, #ClientID AS bigint = NULL
,#TotalTests as int, #WithoutFollowup as int, #FirstFollowup as int,#SecondFollowup as int, #ThirdFollowup as int, #FourthFollowup as int, #FifthFollowup as int
,#Org as varchar(250),#City as varchar(250)
DECLARE cur CURSOR FOR
SELECT Areas.ID, Areas.Name, Cities.ID, Cities.CityName
FROM [dbo].[Areas]
INNER JOIN [dbo].[AreaCities] ON Areas.ID = AreaCities.AreaID
INNER JOIN [dbo].[Cities] ON AreaCities.CityID = Cities.ID
INNER JOIN [dbo].[States] ON States.ID = Cities.StateID
INNER JOIN [dbo].[Countries] ON Countries.ID = States.CountryID
WHERE [Areas].[IsActive] = 1
AND [Cities].[IsActive] = 1
AND [Areas].[CountryID] = 168
OPEN cur
FETCH NEXT FROM cur INTO #AreaID, #AreaName, #CityID, #CityName
WHILE ##FETCH_STATUS = 0
BEGIN
SET #Total = (
SELECT COUNT(1)
FROM [dbo].[ServiceDetails]
INNER JOIN [dbo].[Services] ON [ServiceDetails].[ServiceID] = [Services].[ID]
Where [ServiceDetails].[Status] !='Testing'
AND [ServiceDetails].[Status] !='Pending'
AND [Services].[AreaID] = #AreaID
AND [Services].[CityID] = #CityID
GROUP BY [Services].[AreaID],[Services].[CityID]
)
SET #WithoutFollowup = (
SELECT COUNT(1)
FROM [dbo].[ServiceDetails]
INNER JOIN [dbo].[Services] ON [ServiceDetails].[ServiceID] = [Services].[ID]
Where [ServiceDetails].[Status] !='completed'
AND [ServiceDetails].[IsFollowUp] = 'false'
AND [Services].[AreaID] = #AreaID
AND [Services].[CityID] = #CityID
GROUP BY [Services].[AreaID],[Services].[CityID]
)
SET #FirstFollowup = (
SELECT COUNT(1)
FROM [dbo].[ServiceDetails]
INNER JOIN [dbo].[Services] ON [ServiceDetails].[ServiceID] = [Services].[ID]
Where [ServiceDetails].[Status] !='completed'
AND [ServiceDetails].[IsFollowUp] = 'True'
GROUP BY [Services].[AreaID],[Services].[CityID]
)
INSERT #TEMP# ([Org],[City],[Total],[WithoutFollowup],[FirstFollowup],[SecondFollowup],[ThirdFollowup],[FourthFollowup],[FifthFollowup])
VALUES(#AreaName,#CityName,#Total,#WithoutFollowup,#FirstFollowup,#SecondFollowup,#ThirdFollowup,#FourthFollowup,#FifthFollowup);
FETCH NEXT FROM cur INTO #AreaID, #AreaName, #CityID, #CityName
END
CLOSE cur
DEALLOCATE cur
SELECT * FROM #TEMP#
DROP TABLE #TEMP#

I've accomplished this task using rownumbers and another temporary Table inside the cursor
INSERT INTO #Services#
SELECT ROW_NUMBER() OVER (ORDER BY [Services].[Date]) as 'RowNo',[ServiceDetails].* , [Services].[Date]
FROM [ServiceDetails]
INNER JOIN [Services] ON [Services].[ID] = [ServiceDetails].[VCCTsServiceID]
INNER JOIN [Clients] ON [Clients].[ID] = [ServiceDetails].[ClientID]
WHERE [Clients].[ID] LIKE #ClientID
ORDER BY [Services].[Date]
This #Services# is the exact replica of ServiceDetails table. Now we have all the services given to the client with rownumber and Date. It is sorted on date so we get the followups exactly when they are done. Now you can query what you want.
SET #TotalServices = ( SELECT COUNT(*) FROM #Services# )
SET #FirstSericeDate = (SELECT [#Services#].[Date] FROM #Services# WHERE [#Services#].[RowNo] = 1 )
SET #Status = (SELECT [#Services#].[Status] FROM #Services# WHERE [#Services#].[RowNo] = 1 )
SET #Date1 = (SELECT [#Services#].[Date] FROM #Services# WHERE [#Services#].[RowNo] = 2 )
SET #Status1 = (SELECT [#Services#].[Status] FROM #Services# WHERE [#Services#].[RowNo] = 2)
Then insert your variables into main temptable for reporting
INSERT #TEMP# ([RegNo], . . . [Status], Date1], [Status1] . .)
VALUES(#RegNo, . .. #Status, #Date1 , #Status1, . . );
TRUNCATE TABLE #Services#
FETCH NEXT FROM cur INTO #RegNo

Related

PL/SQL DBMS_OUTPUT.PUT_LINE

i have problem with DBMS_OUTPUT.PUT_LINE i made 2 of them
must one show before salary updated and one after salary updated
but both of them show me the update
only mabye i make something wrong check the code please .
CREATE OR REPLACE PROCEDURE SET_SALARY (P_EMP_ID NUMBER , P_ADD_SAL NUMBER)
IS
V_NAME VARCHAR2(50) ;
V_SALARY NUMBER ;
V_MANG_NAME VARCHAR2(50);
V_MANG_SAL NUMBER ;
V_EMP_ID NUMBER ;
V_MNG_ID NUMBER ;
BEGIN
SELECT LAST_NAME , SALARY
INTO V_NAME , V_SALARY
FROM EMPLOYEES
WHERE EMPLOYEE_ID = P_EMP_ID ;
DBMS_OUTPUT.PUT_LINE (V_NAME || ' Before: '||V_SALARY ); <===(must show for select)
UPDATE EMPLOYEES
SET SALARY = SALARY + P_ADD_SAL
WHERE EMPLOYEE_ID = P_EMP_ID ;
DBMS_OUTPUT.PUT_LINE (V_NAME || ' After: '||V_SALARY ); <==(must show after update)
SELECT E.EMPLOYEE_ID , E.LAST_NAME, E.SALARY ,E.MANAGER_ID,M.LAST_NAME , M.SALARY
INTO V_EMP_ID, V_NAME , V_SALARY ,V_MNG_ID,V_MANG_NAME , V_MANG_SAL
FROM EMPLOYEES E , EMPLOYEES M
WHERE E.MANAGER_ID = M.EMPLOYEE_ID
AND E.EMPLOYEE_ID = P_EMP_ID ;
DBMS_OUTPUT.PUT_LINE (V_MANG_NAME || ' Before: '||V_MANG_SAL );<===(must show for select)
UPDATE EMPLOYEES
SET SALARY = SALARY + ( P_ADD_SAL / 2 )
WHERE EMPLOYEE_ID = V_MNG_ID ;
DBMS_OUTPUT.PUT_LINE (V_MANG_NAME || ' AFTER: '||V_MANG_SAL );<==(must show after update)
END ;
Your problem is that you are never updating the variable values of V_SALARY and V_MANG_SAL after the initial SELECT INTO statements.
If you want to do that you need to add a RETURNING clause to your update statements. Take the first one as an example:
UPDATE EMPLOYEES
SET SALARY = SALARY + P_ADD_SAL
WHERE EMPLOYEE_ID = P_EMP_ID
RETURNING salary INTO v_salary;
That will update the value in the variable V_SALARY with the updated value.

dynamic query showing 'Unclosed quotation mark after the character string '),

i have a stored procedure in which i am getting error 'Unclosed quotation mark after the character string ' having a hard time with the script. please help me to find out what is wrong in my code.
here is my code.
ALTER PROCEDURE [dbo].[usp_Transfer]
#orgid bigint,
#SearchString nvarchar (500) = null,
#LocationId bigint = 0,
#ownerid bigint,
#OrderList varchar(MAX)
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.\
SET NOCOUNT ON;
DECLARE #SQL varchar(MAX)
BEGIN
SET #SQL = 'SELECT ProductID = ii.ProductId,
InvItemId = convert(bigint,0),Name = p.Name,
PrimaryImageID = p.PrimaryImageID,ProductNumberLabel = p.ProductNumberLabel,ProductNumber = p.ProductNumber,
category = isnull(c.Name,''),
qty = ISNULL((SUM(ii.[QuantityOnHand]) - SUM(ii.[QuantitySold])), 0.00),
SalePrice= ISNULL(p.SalePrice, 0.00),
EnteredQuantity=(case when (ISNULL((SUM(ii.[QuantityOnHand]) - SUM(ii.[QuantitySold])), 0.00) > 1) then 1.00 else ISNULL((SUM(ii.[QuantityOnHand]) - SUM(ii.[QuantitySold])), 0.00) end)
,Discount=0,u.UnitName,
u.UnitID
FROM dbo.[Inven] ii
Left Join dbo.[Product] p on ii.ProductId = p.ProductId and p.activestatus=1
Left Join dbo.[category] c on p.DefaultCategoryId = c.CategoryId
Left Join dbo.[Unit] u on p.UnitId=u.UnitId and u.Activestatus=1
WHERE p.OrganizationID = #orgid
AND ii.InventoryID IN(1634)
AND ii.ActiveStatus = 1
AND p.ActiveStatus = 1
AND p.IsDisabled = 0
And p.CanSale = 1
AND ii.InventoryID IN (' + #OrderList + ')
group by ii.ProductId, p.Name, p.PrimaryImageID, p.ProductNumberLabel, p.ProductNumber, c.Name,p.SalePrice,u.unitname,u.UnitID
having ISNULL((SUM(ii.[QuantityOnHand]) - SUM(ii.[QuantitySold])), 0) > 0
Order by p.ProductNumber, p.Name, c.Name '
--EXEC(#SQL)
PRINT(#SQL)
END
END
Two things of note.
First, does #OrderList contain any quotes?
Second, this line:
...' WHERE p.OrganizationID = #orgid '
Should be:
....'WHERE p.OrganizationID = ' + #orgid + '...'
The easy way to test if either of these are the cause of the problem is to comment both out, run it and see if it works, if it does then comment them in one at a time to see which one gives you the error.
Finally, you could rewrite this query and avoid using a dynamic query at all. I guess looking at the query you have done it because of the IN (' + #OrderList + ') clause. These posts might help you rework that section:
Parameterize an SQL IN clause
SQL Server - In clause with a declared variable
Update your SP as below:
Note: there are so many errors if solve one like quotation mark, declare variable #orgid and then conversion error
Your initial error due to : category = isnull(c.Name,''), replace it with category = isnull(c.Name,'''')
alter PROCEDURE [dbo].[usp_Transfer]
#orgid bigint=1,
#SearchString nvarchar (500) = null,
#LocationId bigint = 0,
#ownerid bigint=1,
#OrderList varchar(MAX)='1'
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.\
SET NOCOUNT ON;
DECLARE #SQL varchar(MAX)
BEGIN
SET #SQL = 'SELECT ProductID = ii.ProductId,
InvItemId = convert(bigint,0),Name = p.Name,
PrimaryImageID = p.PrimaryImageID,ProductNumberLabel = p.ProductNumberLabel,ProductNumber = p.ProductNumber,
category = isnull(c.Name,''''),
qty = ISNULL((SUM(ii.[QuantityOnHand]) - SUM(ii.[QuantitySold])), 0.00),
SalePrice= ISNULL(p.SalePrice, 0.00),
EnteredQuantity=(case when (ISNULL((SUM(ii.[QuantityOnHand]) - SUM(ii.[QuantitySold])), 0.00) > 1) then 1.00 else ISNULL((SUM(ii.[QuantityOnHand]) - SUM(ii.[QuantitySold])), 0.00) end)
,Discount=0,u.UnitName,
u.UnitID
FROM dbo.[Inven] ii
Left Join dbo.[Product] p on ii.ProductId = p.ProductId and p.activestatus=1
Left Join dbo.[category] c on p.DefaultCategoryId = c.CategoryId
Left Join dbo.[Unit] u on p.UnitId=u.UnitId and u.Activestatus=1
WHERE p.OrganizationID = '+CAST(#orgid AS VARCHAR(10))+'
AND ii.InventoryID IN(1634)
AND ii.ActiveStatus = 1
AND p.ActiveStatus = 1
AND p.IsDisabled = 0
And p.CanSale = 1
AND ii.InventoryID IN (' + #OrderList + ')
group by ii.ProductId, p.Name, p.PrimaryImageID, p.ProductNumberLabel, p.ProductNumber, c.Name,p.SalePrice,u.unitname,u.UnitID
having ISNULL((SUM(ii.[QuantityOnHand]) - SUM(ii.[QuantitySold])), 0) > 0
Order by p.ProductNumber, p.Name, c.Name '
EXEC(#SQL)
PRINT(#SQL)
END
END

How to separate (split) string with comma in SQL Server stored procedure

I have a checkboxlist. The selected (checked) items are stored in List<string> selected.
For example, value selected is monday,tuesday,thursday out of 7 days
I am converting List<> to a comma-separated string, i.e.
string a= "monday,tuesday,thursday"
Now, I am passing this value to a stored procedure as a string. I want to fire query like:
Select *
from tblx
where days = 'Monday' or days = 'Tuesday' or days = 'Thursday'`
My question is: how to separate string in the stored procedure?
If you pass the comma separated (any separator) string to store procedure and use in query so must need to spit that string and then you will use it.
Below have example:
DECLARE #str VARCHAR(500) = 'monday,tuesday,thursday'
CREATE TABLE #Temp (tDay VARCHAR(100))
WHILE LEN(#str) > 0
BEGIN
DECLARE #TDay VARCHAR(100)
IF CHARINDEX(',',#str) > 0
SET #TDay = SUBSTRING(#str,0,CHARINDEX(',',#str))
ELSE
BEGIN
SET #TDay = #str
SET #str = ''
END
INSERT INTO #Temp VALUES (#TDay)
SET #str = REPLACE(#str,#TDay + ',' , '')
END
SELECT *
FROM tblx
WHERE days IN (SELECT tDay FROM #Temp)
Try this:
CREATE FUNCTION [dbo].[ufnSplit] (#string NVARCHAR(MAX))
RETURNS #parsedString TABLE (id NVARCHAR(MAX))
AS
BEGIN
DECLARE #separator NCHAR(1)
SET #separator=','
DECLARE #position int
SET #position = 1
SET #string = #string + #separator
WHILE charindex(#separator,#string,#position) <> 0
BEGIN
INSERT into #parsedString
SELECT substring(#string, #position, charindex(#separator,#string,#position) - #position)
SET #position = charindex(#separator,#string,#position) + 1
END
RETURN
END
Then use this function,
Select *
from tblx
where days IN (SELECT id FROM [dbo].[ufnSplit]('monday,tuesday,thursday'))
try this
CREATE FUNCTION Split
(
#delimited nvarchar(max),
#delimiter nvarchar(100)
) RETURNS #t TABLE
(
-- Id column can be commented out, not required for sql splitting string
id int identity(1,1), -- I use this column for numbering splitted parts
val nvarchar(max)
)
AS
BEGIN
declare #xml xml
set #xml = N'<root><r>' + replace(#delimited,#delimiter,'</r><r>') + '</r></root>'
insert into #t(val)
select
r.value('.','varchar(max)') as item
from #xml.nodes('//root/r') as records(r)
RETURN
END
GO
usage:
select * from tblx where days in (select val from dbo.split('monday,tuesday,thursday',','))
I think you want this
SELECT * FROM tblx where days in ('Monday','Tuesday','Thursday')
you can get it like this:
var a = "monday,tuesday,thursday";
var sql = string.Format("Select * from tblx where days IN ('{0}')", string.Join("','",a.Split(new[] {','})));
I face the same problem, and i try all the way but not get expected solution. Finally i did like follow. Try it hope it will work...
create Function [dbo].[Split]
(
#RowData NVARCHAR(MAX),
#SplitOn NVARCHAR(5)
)
RETURNS #RtnValue TABLE
(
Id INT IDENTITY(1,1),
Data NVARCHAR(100)
)
AS
BEGIN
DECLARE #Cnt INT
SET #Cnt = 1
WHILE (Charindex(#SplitOn,#RowData)>0)
BEGIN
INSERT INTO #RtnValue (data)
SELECT Data = ltrim(rtrim(Substring(#RowData,1,Charindex(#SplitOn,#RowData)-1)))
SET #RowData = Substring(#RowData,Charindex(#SplitOn,#RowData)+1,len(#RowData))
SET #Cnt = #Cnt + 1
END
INSERT INTO #RtnValue (data)
SELECT Data = ltrim(rtrim(#RowData))
RETURN
END
And in the store procedure put the code like that.
select #ActualTarget= count(*) from UpdateVisitDetails where CreatedBy IN (SELECT [DATA] FROM [dbo].[Split](#AllDATS,',' ))
I have same problem. I tried this.. and this was properly run
ALTER FUNCTION [dbo].[Split]
(
#List varchar(max),
#SplitOn nvarchar(5)
)
RETURNS #RtnValue table
(
Id int identity(1,1),
Value nvarchar(max)
)
AS
BEGIN
IF (len(#List) <=0)
Begin
Return
End
While (Charindex(#SplitOn,#List)>0)
Begin
Insert Into #RtnValue (value)
Select
Value = ltrim(rtrim(Substring(#List,1,Charindex(#SplitOn,#List)-1)))
Set #List = Substring(#List,Charindex(#SplitOn,#List)+len(#SplitOn),len(#List))
End
Insert Into #RtnValue (Value)
Select Value = ltrim(rtrim(#List))
Return
END
Run :
SELECT * FROM dbo.Split('Apple,Banana,Mango',',')
Output:

How to return last identity value generated for a specific table in the current session and the current scope

I am inserting a row in Table1.
I am inserting the last Srno(identity) of this Table1 and some other values in Table2
I am doing all this in one stored procedure
CREATE PROCEDURE proc_test1
(
#MultipleImgsTvp AS testdbtype READONLY,
#ClaimDetailsTvp AS testdbtype1 READONLY
)
AS BEGIN
INSERT INTO dbo.Tbl_ClaimDetails (BranchRemark, BrMkrid, BrMkrdt, BAZClaimNo, HORemark, HoMkrid, hoMkrdt, ClaimType, ContactDetails, VendorName)
SELECT BranchRemark
, BrMkrid
, GETDATE()
, BAZClaimNo
, HORemark
, HoMkrid
, GETDATE()
, ClaimType
, ContactDetails
, VendorName
FROM #ClaimDetailsTvp
DECLARE #id INT = SCOPE_IDENTITY()
DECLARE #ClaimNo VARCHAR(25)
SET #ClaimNo = (
SELECT Em_Branchcdnew
FROM tbl_xyz
WHERE Em_empid = (SELECT BrMkrid FROM #ClaimDetailsTvp)
) + '/' + LEFT(CONVERT(VARCHAR, GETDATE(), 111), 8) + CONVERT(VARCHAR, #ID)
UPDATE Tbl_ClaimDetails
SET ClaimNo = #ClaimNo
WHERE Srno = #ID
----------
INSERT INTO Tbl_ClaimImages (img, id, imgname)
SELECT img
, id
, imgname
FROM #MultipleImgsTvp
----------
END
But i am always getting 0 in ID.
UPDATE
Tbl_ClaimDetails
SrNo(identity) | Remark | BrMkrdt | ...so on
i want to get the last inserted SrNo of Tbl_ClaimDetails
Shouldn't your final insert statement be:
INSERT INTO Tbl_ClaimImages (img, id, imgname)
SELECT img
, #id
, imgname
FROM #MultipleImgsTvp
Raj
If I understand you correctly, you can use the OUTPUT section of the query like so :
INSERT INTO dbo.Tbl_ClaimDetails (BranchRemark, BrMkrid, BrMkrdt, BAZClaimNo, HORemark, HoMkrid, hoMkrdt, ClaimType, ContactDetails, VendorName)
OUTPUT inserted.id INTO #ID
SELECT BranchRemark
, BrMkrid
, GETDATE()
, BAZClaimNo
, HORemark
, HoMkrid
, GETDATE()
, ClaimType
, ContactDetails
, VendorName
FROM #ClaimDetailsTvp
With the OUTPUT section, you can access the inserted row data by using inserted.column

Not able to get data from cursor in oracle

I am trying to get data from oracle database using asp.net but I am not getting any output in cursor while data is present in table:
I am using following stored procedure:
CREATE OR REPLACE PROCEDURE branch_details
( startIndex in int
,pageSize in int
,isSearch in int
,byName in int
,dataDetail in varchar2
, p_cursor out sys_refcursor)
AS
BEGIN
IF isSearch=1 THEN
IF byName=1 THEN
OPEN p_cursor FOR
SELECT *
FROM (SELECT ROW_NUMBER() OVER(ORDER BY branch_id)
AS MyRows
, branch_id, branch_name
, branch_location, bm_name, bm_contact
, bm_email, is_active, max_ua
, (SELECT COUNT(branch_id)
FROM branch_info
WHERE branch_name LIKE
'%'|| dataDetail||'%')
AS RowNumber
FROM branch_info
WHERE branch_name LIKE '%'|| dataDetail||'%')
WHERE MyRows BETWEEN startIndex
AND startIndex+pageSize-1;
ELSE
OPEN p_cursor FOR
SELECT *
FROM (SELECT ROW_NUMBER() OVER(ORDER BY branch_id)
AS MyRows
, branch_id, branch_name, branch_location
, bm_name, bm_contact, bm_email, is_active
, max_ua
, (SELECT COUNT(branch_id)
FROM branch_info
WHERE branch_id LIKE
'%'|| dataDetail||'%')
As RowNumber
FROM branch_info
WHERE branch_id LIKE '%'|| dataDetail||'%')
WHERE MyRows BETWEEN startIndex
AND startIndex+pageSize-1;
END IF;
ELSE
OPEN p_cursor FOR
SELECT *
FROM (SELECT ROW_NUMBER() OVER(ORDER BY branch_id)
AS MyRows
, branch_id, branch_name, branch_location
, bm_name, bm_contact, bm_email
, is_active, max_ua
, (SELECT COUNT(branch_id)
FROM branch_info) AS RowNumber
FROM branch_info)
WHERE MyRows BETWEEN startIndex
AND startIndex+pageSize-1;
END IF;
END;
And using following asp.net code:
List<Paramarray> param = new List<Paramarray>();
param.Add(new Paramarray("#dataDetail", data));
param.Add(new Paramarray("#byName", id?"0":"1"));
param.Add(new Paramarray("#isSearch", isSearch?"1":"0"));
param.Add(new Paramarray("#startIndex", startIndex==1?startIndex.ToString():Convert.ToString(((startIndex-1)*pageSize)+1)));
param.Add(new Paramarray("#pageSize", pageSize.ToString()));
_command.Connection = _connection;
_command.CommandType = CommandType.StoredProcedure;
_command.CommandText = "branch_details";
foreach (Paramarray _param in param)
{
_parameter = new OracleParameter(_param.name,_param.value);
_command.Parameters.Add(_parameter);
}
_command.Parameters.Add("#p_cursor", OracleDbType.RefCursor).Direction = ParameterDirection.Output;
if (_connection.State != ConnectionState.Open) _connection.Open();
_dataReader = _command.ExecuteReader();
dt.Load(_dataReader);
if (_connection.State == ConnectionState.Open) _connection.Close();
My same code for another procedure is working fine and giving me output.
Please help me if I am wrong in my procedure or somewhere else. I am not able to figure the problem.
I am going to wager that your procedure is wrong. Your asp.net code looks fine and without more information it seems to me that the cursor is just not returning any data.
Have you unit tested the procedure or even just the cursor queries?

Resources