Query on a self-referential table - database

Suppose I have this simple table
UserID|Name |Aid ID
1 |Bob | 3
2 |Alice | 1
3 |Ted | 4
4 |Sam | 2
In a query, I would have to list the name of the person, and the name of the person that they aid. I thought about doing a View, but I feel like this could be done in a simple query than creating a view. How would I do that, and how does the query work exactly, like the fundamentals behind it?

you need to join the table to itself
SELECT a."UserID",
a."Name",
b."Name" As AIDName
FROM tableName a
INNER JOIN tableName b
ON a."AidID" = b."UserID"
SQLFiddle Demo

Query will be
select persons.name,aid.name
from your_tablename as persons,
your_tablename as aid
where persons.aidid=aid.userID

Related

How to add data to a single column

I have a question in regards to adding data to a particular column of a table, i had a post yesterday where a user guided me (thanks for that) to what i needed and said an update was the way to go for what i need, but i still can't achieve my goal.
i have two tables, the tables where the information will be added from and the table where the information will be added to, here is an example:
source_table (has only a column called "name_expedient_reviser" that is nvarchar(50))
name_expedient_reviser
kim
randy
phil
cathy
josh
etc.
on the other hand i have the destination table, this one has two columns, one with the ids and the other where the names will be inserted, this column values are null, there are some ids that are going to be used for this.
this is how the other table looks like
dbo_expedient_reviser (has 2 columns, unique_reviser_code numeric PK NOT AI, and name_expedient_reviser who are the users who check expedients this one is set as nvarchar(50)) also this is the way this table is now:
dbo_expedient_reviser
unique_reviser_code | name_expedient_reviser
1 | NULL
2 | NULL
3 | NULL
4 | NULL
5 | NULL
6 | NULL
what i need is the information of the source_table to be inserted into the row name_expedient_reviser, so the result should look like this
dbo_expedient_reviser
unique_reviser_code | name_expedient_reviser
1 | kim
2 | randy
3 | phil
4 | cathy
5 | josh
6 | etc.
how can i pass the information into this table? what do i have to do?.
EDIT
the query i saw that should have worked doesn't update which is this one:
UPDATE dbo_expedient_reviser
SET dbo_expedient_reviser.name_expedient_reviser = source_table.name_expedient_reviser
FROM source_table
JOIN dbo_expedient_reviser ON source_table.name_expedient_reviser = dbo_expedient_reviser.name_expedient_reviser
WHERE dbo_expedient_reviser.name_expedient_reviser IS NULL
the query was supposed to update the information into the table, extracting it from the source_table as long as the row name_expedient_reviser is null which it is but is doesn't work.
Since the Names do not have an Id associated with them I would just use ROW_NUMBER and join on ROW_NUMBER = unique_reviser_code. The only problem is, knowing what rows are null. From what I see, they all appear null. In your data, is this the case or are there names sporadically in the table like 5,17,29...etc? If the name_expedient_reviser is empty in dbo_expedient_reviser you could also truncate the table and insert values directly. Hopefully that unique_reviser_code isn't already linked to other things.
WITH CTE (name_expedient_reviser, unique_reviser_code)
AS
(
SELECT name_expedient_reviser
,ROW_NUMBER() OVER (ORDER BY name_expedient_reviser)
FROM source_table
)
UPDATE er
SET er.name_expedient_reviser = cte.name_expedient_reviser
FROM dbo_expedient_reviser er
JOIN CTE on cte.unique_reviser_code = er.unique_reviser_code
Or Truncate:
Truncate Table dbo_expedient_reviser
INSERT INTO dbo_expedient_reviser (name_expedient_reviser, unique_reviser_code)
SELECT DISTINCT
unique_reviser_code = ROW_NUMBER() OVER (ORDER BY name_expedient_reviser)
,name_expedient_reviser
FROM source_table
it is not posible to INSERT the data into a single column, but to UPDATE and move the data you want is the only way to go in that cases

SQL Server Insert Using View

This is a simplified example of what I want to do. Assume there is table named contractor that looks like this:
name | paid_adjustment_amount | adj_date
Bob | 1000 | 4/7/2016
Mary | 2000 | 4/8/2016
Bill | 5000 | 4/8/2016
Mary | 4000 | 4/10/2016
Bill | (1000) | 4/12/2016
Ann | 3000 | 4/30/2016
There is a view of the contractor table, let's call it v_sum, that is just a SUM of the paid_adustment_amount grouped by name. So it looks like this:
name | total_paid_amount
Bob | 1000
Mary | 6000
Bill | 4000
Ann | 3000
Finally, there is another table called to_date_payment that looks like this:
name | paid_to_date_amount
Bob | 1000
Mary | 8000
Bill | 3000
Ann | 3000
Joe | 4000
I want to compare the information in the to_date_payment table to the v_sum view and insert a new row in the contractor table to show an adjustment. Something like this:
INSERT INTO contractor
SELECT to_date_payment.name,
to_date_payment.paid_to_date_amount - v_sum.total_paid_amount,
GETDATE()
FROM to_date_payment
LEFT JOIN v_sum ON to_date_payment.name = v_sum.name
WHERE to_date_payment.paid_to_date_amount - v_sum.total_paid_amount <> 0
OR v_sum.name IS NULL
Are there any issues with using a view for this? My understanding, please correct me if I'm wrong, is that a view is just a result set of a query. And, since the view is of the table I'm inserting new records into, I'm afraid there could be data integrity problems.
Thanks for the help!
In order to fully understand what you are doing, you should also provide the definition for v_sum. Generally speaking, views might provide some advantages, especially when indexed. More details can be found here and here.
Simple usage of views do not provide performance benefits, but they are very good of providing abstraction over tables.
In your particular case, I do not see any problem in JOINing with the view, but I would worry about potential problems related to:
1) JOIN using VARCHARs instead of integer - ON to_date_payment.name = v_sum.name - if possible, try to JOIN on integer (ids or foreign keys ids) values, as it is faster (indexes applied on integer columns will have a smaller key, comparisons are slightly faster).
2) OR in queries - usually leads to performance problems. One thing to try is to change the SELECT like this:
SELECT to_date_payment.name,
to_date_payment.paid_to_date_amount - v_sum.total_paid_amount,
GETDATE()
FROM to_date_payment
JOIN v_sum ON to_date_payment.name = v_sum.name
WHERE to_date_payment.paid_to_date_amount - v_sum.total_paid_amount <> 0
UNION ALL
SELECT to_date_payment.name,
to_date_payment.paid_to_date_amount, -- or NULL if this is really intended
GETDATE()
FROM to_date_payment
-- NOT EXISTS is usually faster than LEFT JOIN ... IS NULL
WHERE NOT EXISTS (SELECT 1 FROM v_sum V WHERE V.name = to_date_payment.name)
3) Possible undesired result - by default, arithmetic involving NULL returns NULL. When there is no match in v_sum, then v_sum.total_paid_amount is NULL and to_date_payment.paid_to_date_amount - v_sum.total_paid_amount will evaluate to NULL. Is this correct? Maybe to_date_payment.paid_to_date_amount - ISNULL(v_sum.total_paid_amount, 0) is intended.

Dynamic Sql Filter using tables

Any ideas on how this should be done with T-SQL queries?
I have two tables, Table A contain records I want to return but filter through. Table B contains the list of filters and class categories. New records are added to Table A all the time. The goal is to dynamically categorized records in Table A based on the filters listed in Table B.
Example:
Table A
Name
------------
John Doe
Mary Lamb
Peter Pan
Tom Sawyer
Suzie Lamb
Nancy Lamb
Josh Reddin
Table B:
Filter | Category
----------------------
John%Doe% | Team 1
%Lamb% | Team 2
Tom% | Team 1
Desired output:
Name | Category
John Doe | Team 1
Tom Sawyer | Team 1
Mary Lamb | Team 2
Suzie Lamb | Team 2
Nancy Lamb | Team 2
Peter Pan |
Josh Reddin |
I thought about doing the following but not sure if that's the best solution:
SELECT Filter, category from TableB (Get list of filters)
Using SQL Loop through filters returned in (1.) and find matches in Table A using LIKE.
Example:
SELECT name, Category
FROM Table A, Table B
WHERE Table A.Name Like (CURRENT filter FROM B)
Insert/append record(s) returned in (2.) into TempTable
SELECT *
FROM TempTable (this returns Names and categories as shown in the desired output)
UNION
SELECT *
FROM Table A
RIGHT OUTER JOIN TempTable on NAME
WHERE Category in null
(This returns rows with no categories found...Peter Pan and Josh Reddin)
Any ideas?
How about performance?
Thanks.
You can use combination of like and left join
select a.Name,b.Category
from tableA a left join tableB b on a.name like b.Filter

SQL Query returns multiple rows of the same record when View includes one-to-many table

In MS-SQL, I have a View 'ListingResult' which contains rows from tables 'ListingCategoryXref' and 'Listing'. This is the View statement:
SELECT
dbo.Listing.ListingName,
dbo.Listing.ListingId,
dbo.ListingCategoryXref.CategoryId
FROM dbo.Listing INNER JOIN
dbo.ListingCategoryXref ON dbo.Listing.ListingId = dbo.ListingCategoryXref.ListingId
GROUP BY
dbo.Listing.ListingName,
dbo.Listing.ListingId,
dbo.ListingCategoryXref.CategoryId
Listings can have many rows in ListingCategoryXref, thus.
ListingResult (View)
Listing (table)
ListingId ListingName StateId
1 Toms bar 3
2 French place 5
ListingCategoryXref (table)
ListingId CategoryId
1 10
1 15
The query below returns a row per Listing per ListingCategoryXref.
SELECT TOP(26)
[ListingResult].[ListingId],
[ListingResult].[ListingName]
FROM [ListingResult]
WHERE [ListingResult].[StateId] = 3
So 'Tom's Bar' is returned twice as it has two categories. I figure I can either change the query above, or change the ListingResult View in SQL. I still need to return 26 results which I can't dictate if I use a wrapped select statement with ROW_NUMBER() OVER(PARTITION BY ListingId. (Is that true?) I'm using LLBLGen to access the DB so I'd prefer to change the view, if that is possible? Apologies for my newness to SQL being that obvious.
From the query above, the following result will be returned...
ListingName | ListingId | CategoryId
Toms bar | 1 | 10
Toms bar |1 | 15
If you only want Toms bar to be returned once, you'll need to remove the CategoryId column from the result set, and the group by clause, or add CategoryId to an agrgate function, and remove it from the group by clause i.e.
SELECT
dbo.Listing.ListingName,
dbo.Listing.ListingId,
COUNT(dbo.ListingCategoryXref.CategoryId) as Categories
FROM dbo.Listing
INNER JOIN dbo.ListingCategoryXref ON dbo.Listing.ListingId = dbo.ListingCategoryXref.ListingId
GROUP BY dbo.Listing.ListingName, dbo.Listing.ListingId
Which will return...
ListingName | ListingId | Categories
Toms bar | 1 | 2
Can you give an example of what you would like to see?

Merging of 2 Tables but different value of fields

I am using MS SQL to create a report to merge 2 tables. The problem is that I need 2 different headers and 1 column needs to have values from 2 different fields from the 2 tables.
Sample
Material | Plant
-------------------------------------------------
Component | Quantity
XXX - Material | ABC--Plant
--------------------------------------------------
YYYY-Component | 3000- Quantity
Is this even possible?
select * from
(
(select *,rn=row_number()over(order by column1) from table1)x,
(select *,rn1=row_number()over(order by column2) from table2)y
)
where x.rn=y.rn1
Firstly you need to give a extra column say rownumber,then repeat same for table2
then you can join using the row_numbers

Resources