How to retrieve a column value using a variable - sql

I have a single SQL table with columns Mary, Joe, Pat and Mick
I have rows of values for each persons weekly expenses
I want a single sproc to query a persons weekly expense value
i.e. a sproc that takes two variables #PersonsName and #WeekNumber and returns a single value
It wont work for me. It will work if I specify the persons name in the query but not if I pass the persons name to the query.
I'm pulling my hair out - is this something to do with Dynamic SQL?

Not sure if you are really digging into performance, scalability etc. as your scenario seems like a small personal tool. But still... as juergen suggested, you better design the schema in a different way. your current design won't scale easily if you want to add one more person to your database.
Instead, you can have something like
a persons table(person name, person Id)
an expenses table (week number, person id, expense)
This scales well. and with indexing on person id your queries can be faster
Suggestions apart,
Can I pass variable to select statement as column name in SQL Server seems to provide answer for your question

Related

Transpose to Count columns of Boolean values on Access SQL

Ok, so I have a Student table that has 6 fields, (StudentID, HasBamboo, HasFlower, HasAloe, HasFern, HasCactus) the "HasPlant" fields are boolean, so 1 for having the plant, 0 for not having the plant.
I want to find the average number of plants that a student has. There are hundreds of students in the table. I know this could involve transposing of some sort and of course counting the boolean values and getting an average. I did look at this question SQL to transpose row pairs to columns in MS ACCESS database for information on Transposing (never done it before), but I'm thinking there would be too many columns perhaps.
My first thought was using a for loop, but I'm not sure those exist in SQL in Access. Maybe a SELECT/FROM/WHERE/IN type structure?
Just hints on the logic and some possible reading material would be greatly appreciated.
you could just get individual totals per category:
SELECT COUNT(*) FROM STUDENTS WHERE HasBamboo
add them all up, and divide by
SELECT COUNT(*) FROM STUDENTS
It's not a great database design though... Better normalized would be:
Table Students; fields StudentID, StudentName
Table Plants; fields PlantID, PlantName
Table OwnedPlants; fields StudentID,PlantID
The last table then stores records for each student that owns a particular plant; but you could easily add different information at the right place (appartment number to Students; Latin name to Plants; date aquired to OwnedPlants) without completely redesigning table structure and add lots of fields. (DatAquiredBamboo, DateAquiredFlower, etc etc)

stored procedure that returns in one row duplicate column names and converts 1->N to a string

I'm trying to put all the below in a single stored procedute that returns a single row because the data is up on Sql Azure and the rule for it is do everything in a single query with a single return.
I have the following tables:
Person (
PersonId
FirstName
...
)
CompanyDomains (
CompanyId
EmailDomain
)
Company (
CompanyId
CompanyName
Billing_PersonId
Admin_PersonId
...
)
I have two problems here. The first is I want to get all the elements of a Company row, and the 2 Person rows of data. That's easy with a join. But the columns for the 2 person columns will have duplicate names. I can do 'as' one by one, which is a pain as the database schema is still in a state of flux. Is there a global way to apply 'as' so all the columns brought in from Billing_PersonId get a Billing_ prepended to the column name and Admin_ prepended to the admin column name?
The second is there is a 1->N list of company domains. Is there a way to pull all those and add a column that is a single string that has "domain1;domain2;" in it? We have the distinct domains in the CompanyDomain table so we can quickly find the company that owns any domain. But a single string works fine when I'm reading the company in.
I know single SQL selects pretty well. But I've got very little experience with stored procedures (aside from calling them) and so what I'm asking here may be basic. If so, sorry. And again, this is for Sql Azure.
thanks - dave
If you are using Azure, then you application should be able to parse XML.
Write a stored procedure to join the three tables, select the data given an input like company id, and return an xml record containing information from all three.
Look at the following references.
FOR XML
http://msdn.microsoft.com/en-us/library/ms178107.aspx
CREATE PROCEUDRE
http://msdn.microsoft.com/en-us/library/ms187926.aspx
If you need more help, you need to post a simple schema with sample data.
USE MY EXAMPLE BELOW FOR SCHEMA + DATA
sql select a field into 2 columns
1 - Without detailed information, not one will be able to help you.
2 - Try it on your own. I can give you the answer but you will not learn anything.
Sincerely
John

SQL query using fn_Split to find multiple values in column

This is a followup to my earlier question which got me part of the way to the goal.
Here is what I'm starting with:
SELECT * FROM MyTable WHERE County IN (SELECT value From dbo.fn_Split(#counties, ','))
Here's the scenario: In my table I've got a column named County. Each record can have multiple counties in the County column delimited with commas (I know this is bad form, I didn't do it). For example: county1, county22, county41. Some records may have only one county (say county13) others might have all the counties. So: county1, count2, county3... through county45 (yes, it's terrible, I know).
In the app I'm trying to build users can select multiple counties or even all counties in the same format as above (county1, county2, county3...). Thanks to Martin's help in the previous question I can get it to return records that have each of the counties individually but not the records that might contain all of the counties.
For example: The user selects county4, county26. I need to have the records returned that have just county4 and county26 as well as any that might contain both of them as part of a larger set (like all 45 of them).
Hope this is clear and I didn't make it more convoluted than necessary. Any assistance is very, very, very much appreciated!
To illustrate:
County
Record1 county1, county14, county26
Record2 county14
Record3 county1, county2, ... through county45
User Submission: county1, county26
Returns: Record1 and Record3
Not sure if I understood the question, but here is how I interpret it:
You need to return rows from your table for one or more selected items.
Also, you want to be able to select ALL items at once without passing the whole list.
I'd do that using Stored Procedure with 2 parameters:
#Selection SMALLINT
#TVP_County CountyTableType (It is Table Valued Variable. See: https://msdn.microsoft.com/en-us/library/bb510489.aspx)
If #Selection = 1 then you join #TVP_County with your table to get results.
If #Selection = 0 you return ALL records from your table w/o join and do not use #TVP_County at all.
If #Selection = -1 then you exclude #TVP_County items from your table. In that case you will be able to do a reverse marks. User will be able to select just few counties, which he/she does not want to see.
Of cause, within a stored procedure you have to implement the logic to run three different queries depending on the first parameter.

How to append two columns into one column in SQL?

I have two columns in my Table called as Workers - Technicians. In Workers I have name of workers, and in Technicians I have name of technicians who is working in company. Here is how it looks:
Workers Technicians
Andy Kevin
Conan Jason
Jay Ray
Donald Daryl
Martin .
Mark .(rows goes on)
.
.(rows goes on)
What I want to do is to append these rows and having a column called Employees. Here what i want:
Employees
Andy
Conan
Jay
Donald
Martin
Mark
Kevin
Jason
Ray
Daryl
.
.
I don't want to create another table, I just want to add a new column. How would i do this?
An union statement should do the job here. Something like this:
select Name from Workers-Technitians where Worker not null
UNION
select Name from Workers-Technitians where Technitian not null
Keep in mind that both queries must have an equal column count when using an union
Assuming your table is named "staff", you could do something like this.
select distinct employees from (
select workers as employees from staff s1
union select technicians as employees from staff s2
) as emps
Perhaps you need to take another look at your design, though. Adding a third column won't work out for you because the first two columns represent two rows. In fact, there already appears to be a forced relationship between the workers and technicians-- they seem to be bundled together in the same record for no particular reason.
Consider starting fresh with an Employee table, with one employee per row, and abandon the existing table. You can maintain employee attributes in that table if the requirements are simple, or join a separate table of attributes for more complex cases. In either case, normalizing your data will make your life easier and use of a union to join columns will be unnecessary.
I also don't understand fully what you want to do (mainly because of this: if, say, a row has "Andy" in Workers and "Kevin" in Technicians, what will you put in Employees? Andy or Kevin?), but to add a new column to the table and then fill it with data you need to:
Add it (assuming your table is named Table and 100 chars are enough for the new column):
alter table [Table] add [Employees] nvarchar(100) null
Fill it:
update [Table] set [Employees] = [Workers]
-- or:
update [Table] set [Employees] = [Technicians]
I believe what you really want is a new table, Employees, and to change the Workers and Technicians into relationships drawn from it. For that, see the link Simon gave you about database normalization.
I don't entirely understand your question but you don't want to add an additional column, this introduces (more) data redundancy and will make any future updates or querying more difficult. Use one of the SELECT query solutions given and seriously consider re-factoring your two existing separate columns into a single column. I suggest you take a look at database normalisation if you're not already familiar with the concept.

Basic question: how to properly redesign this schema

I am hopping on a project that sits on top of a Sql Server 2008 DB with what seems like an inefficient schema to me. However, I'm not an expert at anything SQL, so I am seeking for guidance.
In general, the schema has tables like this:
ID | A | B
ID is a unique identifier
A contains text, such as animal names. There's very little variety; maybe 3-4 different values in thousands of rows. This could vary with time, but still a small set.
B is one of two options, but stored as text. The set is finite.
My questions are as follows:
Should I create another table for names contained in A, with an ID and a value, and set the ID as the primary key? Or should I just put an index on that column in my table? Right now, to get a list of A's, it does "select distinct(a) from table" which seems inefficient to me.
The table has a multitude of columns for properties of A. It could be like: Color, Age, Weight, etc. I would think that this is better suited in a separate table with: ID, AnimalID, Property, Value. Each property is unique to the animal, so I'm not sure how this schema could enforce this (the current schema implies this as it's a column, so you can only have one value for each property).
Right now the DB is easily readable by a human, but its size is growing fast and I feel like the design is inefficient. There currently is not index at all anywhere. As I said I'm not a pro, but will read more on the subject. The goal is to have a fast system. Thanks for your advice!
This sounds like a database that might represent a veterinary clinic.
If the table you describe represents the various patients (animals) that come to the clinic, then having properties specific to them are probably best on the primary table. But, as you say column "A" contains a species name, it might be worthwhile to link that to a secondary table to save on the redundancy of storing those names:
For example:
Patients
--------
ID Name SpeciesID Color DOB Weight
1 Spot 1 Black/White 2008-01-01 20
Species
-------
ID Species
1 Cocker Spaniel
If your main table should be instead grouped by customer or owner, then you may want to add an Animals table and link it:
Customers
---------
ID Name
1 John Q. Sample
Animals
-------
ID CustomerID SpeciesID Name Color DOB Weight
1 1 1 Spot Black/White 2008-01-01 20
...
As for your original column B, consider converting it to a boolean (BIT) if you only need to store two states. Barring that, consider CHAR to store a fixed number of characters.
Like most things, it depends.
By having the animal names directly in the table, it makes your reporting queries more efficient by removing the need for many joins.
Going with something like 3rd normal form (having an ID/Name table for the animals) makes you database smaller, but requires more joins for reporting.
Either way, make sure to add some indexes.