I'm new with SQL Reporting Services 2008 and cannot find out how to do something that should be simple.
What I have is a single select parameter that is populated with a list of salesman from a query. This works great. And I have the dataset query responding to this parameter working well. So my reports for a single salesman are working fine.
My problem is that I would also like to have an option that is ALL Salesman so that the manager can print out a complete list.
Any suggestions on how to do this.
I usually UNION ALL a custom value to the top of my query with a special value that would indicate to my later query that it should not filter.
I usually use NULL, 0, or '%' for this.
Something like:
SELECT 0 [UserId], '(All Users)' [Username]
UNION ALL
SELECT
[UserId],
[Username]
FROM
dbo.[Users]
And then, in the later query:
SELECT * FROM Data WHERE (UserID = #UserID OR #UserID = 0)
Your sales person query probably looks like this:
SELECT SalesPersonName FROM SalesPerson ORDER BY SalesPersonName ASC
You should change it to this:
SELECT 1 as SortOrder, SalesPersonName FROM SalesPerson
UNION SELECT 0 as SortOrder, 'All' ORDER BY SortOrder, SalesPersonName
Now your query will return:
All
Adam
Barry
Steve
...
Now when you pull your data for the report you can do:
WHERE (SalesPersonName = #SalesPersonName OR #SalesPersonName='All')
And make sure you set the default to 'All' if that is what your manager wants.
Related
In our company we have a windows application that we can't develop it any more. This application use one of our live databases.
there is a query like this, that we spend a lot of resource to response this expensive query:
SELECT * FROM City
My question is, is there any way that when this query execute to database, override it with some thing else. For example change it to:
SELECT TOP 10 Name, Code FROM City
Spinning on the idea in #Stu's comment...
Table is renamed into City_Table (sqlfiddle does not work at the time of writing, sorry):
CREATE TABLE City_Table (Code INT, Name VARCHAR(20))
GO
INSERT INTO City_Table (Code, Name)
SELECT 1, 'City1'
UNION ALL
SELECT 2, 'City2'
UNION ALL
SELECT 3, 'City3'
Then a view could try to check the last command issued from current spid:
CREATE VIEW City
AS
SELECT Code, [Name] FROM
(
SELECT ROW_NUMBER() OVER (ORDER BY Code) rownum, Code, [Name]
FROM City_Table
) sub
WHERE
LTRIM(RTRIM(
(SELECT TEXT as query
FROM sys.dm_exec_connections
CROSS APPLY sys.dm_exec_sql_text(most_recent_sql_handle)
WHERE session_id = (SELECT ##SPID)
)
))
!= 'SELECT * FROM City'
OR sub.rownum <= 2
Then a query SELECT * FROM City will return
Code
Name
1
City1
2
City2
whereas a query like SELECT * FROM City ORDER BY 1 will return
Code
Name
1
City1
2
City2
3
City3
But to be honest: I'm not sure at all if this is a reliable way to find the last issued command in a specific application's scenario. And for sure querying sys views by an app user might raise security issues. Just been curious to test it out.
I have a legacy VB6 application that's connected to SQL Server where all data is stored. I'm creating a report for the user where I'll need to pass 2 dates (FROM and TO). In SQL Server, I have created a few views that fulfill all my criteria and use the data from there to populate a dbo.tblTempTable (which is not actually #tempTable, but a normal table). For now the dates are hardcoded, and I'm struggling with finding a way of passing those dates. I'm pretty sure I am unable to pass parameters to a view. To populate the table I have a simple stored procedure that goes like this....
TRUNCATE TABLE dbo.tbl_TTableReport
INSERT INTO tbl_TTableReport (UserID, CompanyID, CompanyName, Sold, Voided, Returned, Subtotal)
SELECT
1234 AS USERID, CompanyID, CompanyName,
Sold, Voided, Returned, Subtotal
FROM dbo.vCompanyInfo
So in this select statement, every piece of data comes from my final view ..vCompanyInfo. Sold, Voided, and Returned need to be filtered by the FROM and TO dates. How would I do something like that?
EDITED. I'm trying to create a stored procedure but I'm getting some weird errors...I have never create a complex multi SELECT statement SP before so I'm still trying to work out the kinks.
This is me trynig to build a SP with select statement, but I keep seeing the same error : Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.
TRUNCATE TABLE dbo.tbl_TTableReport
INSERT INTO tbl_TTableReport
(UserID
, CompanyID)
, CompanyName)
SELECT 1234 AS USERID
,(Select CompanyID from dbo.tblMainInv)
,(select CompanyName from dbo.tblCompanies)
For both the CompanyID and companyName there are about 30 values. I'm trying to have them get loaded into the table, I don't know where my error is.
I recommend you create an ADP Access project to connect to your SQL Server database. This allows you more control over the queries that you send to the Sql Server for reports and data entry forms. When creating the project file you designate the server and database with which you need to connect to. Then setting up the data source for your report is as simple as including the select statement to issue against the database into the data source of the report. You can also refer to text boxes on forms or have automatic prompts for parameters.
As for the error you are getting in your second query in your edit... you are using the sub-query as an expression. SQL Server is being nice in letting you use a sub-query as one of the values to output in your select statement, but it's expecting just that... one value. So you could do something like:
Select
(select count(*) from MyTableValues) as CountTotal,
(select sum(*) from MyTableValues) as SumTotal
However, what you are trying to do is return several rows when SQL Server is expecting you to return just one. If you want to join the data of two tables, you use a join... something like:
SELECT 1234 AS USERID, CompanyID, CompanyName
from dbo.tblMainInv
join dbo.tblCompanies
on tblMainInv.CompanyID = tblCompanies.CompanyID
Which is probably something that your view dbo.vCompanyInfo probably already looks like.
If your determined to use your temp table approach (although I highly recommend you reconsider as your just making more work for future maintenance)... this is something that your procedure might look like:
GO
CREATE PROCEDURE sp_LoadReportData
(
#UserID as int,
#StartDate as datetime,
#EndDate as datetime
) AS
delete from tbl_TTableReport
where USERID = #UserID
INSERT INTO tbl_TTableReport
(UserID, CompanyID, CompanyName, Sold, Voided, Returned, Subtotal)
SELECT
#UserID AS USERID,
CompanyID,
CompanyName,
Sold,
Voided,
Returned,
Subtotal
FROM vCompanyInfo
where
Sold between #StartDate and #EndDate
and Voided between #StartDate and #EndDate
and Returned between #StartDate and #EndDate
GO
You would then call the procedure with the filters you want and send the UserID as a parameter like this:
exec sp_LoadReportData 1234, '1/1/2016', '1/20/2016'
But this still doesn't solve your problem... because you'll still have to send the UserID as a parameter in your report's data source like:
select * from tbl_TTableReport where UserID=1234
Unless you want to create a table and procedure for every user, you should really rethink your strategy and learn how to do it the standard way.
I have two tables: EmployeeMaster and EmployeeDetails. The schema of both are as below:
Sample data in both tables is shown:
I want to generate the hierarchy using EmployeeDetails table primarily. This table contains a column named: Manager. The EmployeeId of the Manager needs to be picked from the table EmployeeMaster table.
This is how the hierarchy needs to be formed. An EmployeeId is passed as a parameter to a stored procedure. The two supervisors of this Employee needs to be picked and 10 employees below this employee in seniority needs to be picked.
For instance, I pass the EmployeeId of Josh.Berkus to the stored procedure. The stored procedure query should return hierarchy as below:
I want the final output in this format:
Employee_Id .... Manager_Id
----------- .... ------------
Please note that Manager_Id is the EmployeeId of Manager.
I tried using a CTE with union all query, but not able to get it correctly.
Actually you will need to work out the recursivity since on manager can have a manager...
take a look at:
http://msdn.microsoft.com/en-us/library/ms190766(v=sql.105).aspx
http://msdn.microsoft.com/en-us/library/ms186243(v=sql.105).aspx
The thing is that your going to need 2 queries... one to go "up" the hierarchy and one to go down... and then union the results...
why don't you merge the two tables, since one person cant have 2 managers right?!? Specially because a manager is also a employee... this will simplify everything...
You can use a CROSS JOIN to create a link between all your records and then you can put the condition to select only those columns that have a manager-employee relationship between them.
The code should be something like this:
SELECT
ed.employeeid 'Employee ID',
em.employeeid 'Manager ID',
FROM EMPLOYEEMASTER em CROSS JOIN EMPLOYEEDETAILS ed
WHERE ed.manager = em.username
You’ll need to implement some recursion here in order to get full hierarchy.
Here is a quick and dirty example of how you can implement this to get manager hierarchy. You would need something similar for lower level hierarchy too
create function dbo.GetManagerHierarchy
(
#EmpID int
)
returns varchar(100)
as
begin
declare #result varchar(100)
declare #managerId int
SET #managerId = (select top 1 Manager from EmployeeDetails where EMployeeId)
if #managerId is not null then
SET #result = dbo.GetManagerHierarchy(#managerID) + '-' + CONVERT(varchar(100), #managerId) +
else
SET #result = ''
return #result
end
Following is example of SQL database query
SELECT *
FROM suppliers
WHERE supplier_name not like 'T%';
This query will returns the records where supplier_name does not starts with T
But how can I achieve the same functionality in salesforce?
There's no select *, so you have to specifiy the exact fields to query, you'd then use NOT and LIKE, e.g.
SELECT id,name, otherFields from suppliers where NOT supplier_name like 'T%'
You can also use something like this: SELECT 'fieldNamesNeeded' FROM suppliers WHERE supplier_name !=:'T%'
Writing my first SQL query to run specifically as a SQL Job and I'm a little out of my depth. I have a table within a SQL Server 2005 Database which is populated each day with data from various buildings. To monitor the system better, I am attempting to write a SQL Job that will run a query (or stored procedure) to verify the following:
- At least one row of data appears each day per building
My question has two main parts;
How can I verify that data exists for each building? While there is a "building" column, I'm not sure how to verify each one. I need the query/sp to fail unless all locations have reported it. Do I need to create a control table for the query/sp to compare against? (as the number of building reporting in can change)
How do I make this query fail so that the SQL Job fails? Do I need to wrap it in some sort of error handling code?
Table:
Employee RawDate Building
Bob 2010-07-22 06:04:00.000 2
Sally 2010-07-22 01:00:00.000 9
Jane 2010-07-22 06:04:00.000 12
Alex 2010-07-22 05:54:00.000 EA
Vince 2010-07-22 07:59:00.000 30
Note that the building column has at least one non-numeric value. The range of buildings that report in changes over time, so I would prefer to avoid hard-coding of building values (a table that I can update would be fine).
Should I use a cursor or dynamic SQL to run a looping SELECT statement that checks for each building based on a control table listing each currently active building?
Any help would be appreciated.
Edit: spelling
You could create a stored procedure that checks for missing entries. The procedure could call raiserror to make the job fail. For example:
if OBJECT_ID('CheckBuildingEntries') is null
exec ('create procedure CheckBuildingEntries as select 1')
go
alter procedure CheckBuildingEntries(
#check_date datetime)
as
declare #missing_buildings int
select #missing_buildings = COUNT(*)
from Buildings as b
left join
YourTable as yt
on yt.Building = b.name
and dateadd(dd,0, datediff(dd,0,yt.RawDate)) =
dateadd(dd,0, datediff(dd,0,#check_date))
where yt.Building is null
if #missing_buildings > 0
begin
raiserror('OMG!', 16, 0)
end
go
An example scheduled job running at 4AM to check yesterday's entries:
declare #yesterday datetime
set #yesterday = dateadd(day, -1, GETDATE())
exec CheckBuildingEntries #yesterday
If an entry was missing, the job would fail. You could set it up to send you an email.
Test tables:
create table Buildings (id int identity, name varchar(50))
create table YourTable (Employee varchar(50), RawDate datetime,
Building varchar(50))
insert into Buildings (name)
select '2'
union all select '9'
union all select '12'
union all select 'EA'
union all select '30'
insert into YourTable (Employee, RawDate, Building)
select 'Bob', '2010-07-22 06:04:00.000', '2'
union all select 'Sally', '2010-07-22 01:00:00.000', '9'
union all select 'Jane', '2010-07-22 06:04:00.000', '12'
union all select 'Alex', '2010-07-22 05:54:00.000', 'EA'
union all select 'Vince', '2010-07-22 07:59:00.000', '30'
Recommendations:
Do use a control table for the buildings - you may find that one
already exists, if you use the Object
Explorer in SQL Server Management
Studio
Don't use a cursor or dynamic SQL to run a loop - use set based
commands instead, possibly something
like the following:
SELECT BCT.Building, COUNT(YDT.Building) Build
FROM dbo.BuildingControlTable BCT
LEFT JOIN dbo.YourDataTable YDT
ON BCT.Building = YDT.Building AND
CAST(FLOOR( CAST( GETDATE() AS FLOAT ) - 1 ) AS DATETIME ) =
CAST(FLOOR( CAST( YDT.RawDate AS FLOAT ) ) AS DATETIME )
GROUP BY BCT.Building