SQL Server: Replicate data from multiple tables into one - sql

Is it possible to replicate data from multiple tables into one real time?
For example I have 3 tables:
Table: DriverLocation
Columns: DriverId, Latitude, Longtide, GpsLastUpdate, Speed, ...
Table: Driver
Columns: DriverId, FirstName, LastName, Address, IsActive, ...
Table: Job
Columns: JobId, DriverId, JobName, Pickup, Delivery, ...
I'd like to create a join query between these 3 tables and in real time publish that data into a table called RealTimeDriverInfo.
Example (pseudo code):
Driver(FirstName, LastName)
JOIN DriverLocatoin(Latitude, Longitude)
JOIN Job(JobName)
PUT RESULT IN REAL TIME INTO => RealTimeDriverInfo table
Is that possible?
EDIT: NOTE:
The reason I want the data to be in a table is because I would like to use this c# library to get real time notifications from a table, this libarary only works with tables and unfortunately you cannot join multiple tables only monitor one table, the library is SQLTableDependency
.NET Library to monitor chagnes in a SQL Table (it can only work with tables, NOT views and you can only monitor one table you cannot join multiple tables)
https://github.com/christiandelbianco/monitor-table-change-with-sqltabledependency
This is why I somehow need to join multiple tables into one table

First, a simple view may do what you want:
CREATE v_RealTimeDriverInfo
SELECT D.FirstName, D.LastName, DL.Latitude, DL.Longitude, J.JobName
FROM Driver D JOIN
DriverLocation DL
ON D.DriverID = DL.DriverID JOIN
Job J
ON J.DriverID = D.DriverID;
with indexes on the columns used for JOINing, this would usually be fast enough when querying. This is the "standard" way to do what you want.
If you actually want a separate "virtual" table that is always up-to-date, then you want something akin to a materialized view, which SQL Server supports as indexed views. The idea is that the index is maintained "real-time" as the underlying data changes.
For your example, it would look like:
CREATE v_RealTimeDriverInfo
SELECT D.FirstName, D.LastName, DL.Latitude, DL.Longitude, J.JobName
FROM Driver D JOIN
DriverLocation DL
ON D.DriverID = DL.DriverID JOIN
Job J
ON J.DriverID = D.DriverID;
CREATE UNIQUE CLUSTERED INDEX v_RealTimeDriverInfo_pk ON (D.FirstName, D.LastName, DL.Latitude, DL.Longitude, J.JobName);

Is inserting into a different table necessary? A view would suffice in this instance. I am assuming that JobId is an integer that increments by one with each job. I use CROSS APPLY to pull in the most recent location and job. You'll also have to have some logic to determine whether or not the driver is on an active job.
select a.FirstName FirstName
,a.LastName LastName
,b.Latitude Latitude
,b.Longitude Longitude
,c.JobName JobName
from Driver a
cross apply (
select top 1
*
from DriverLocation b
where b.DriverId = a.DriverId
order by b.GpsLastUpdate desc
) b
cross apply (
select top 1
c.*
from Job c
where c.DriverId = a.DriverId
order by c.JobId desc
) c

Sure you can, just a quick couple of JOINS. But it seems that creating a view would probably serve you a little better.
INSERT INTO RealTimeDriverInfo (FirstName,LastName,Latitude,Longitude,JobName)
SELECT D.FirstName, D.LastName,DL.Latitude, DL.Longitude,J.JobName
FROM Driver D
INNER JOIN DriverLocation DL on D.DriverID = DL.DriverID
INNER JOIN Job J on J.DriverID = D.DriverID

Related

Complex SQL Query with Dead Ends and 7 Tables

I was tasked with creating a complex query that incudes all of the data from all of the tables minus the Keys. I am having an issue with the dead end tables and how to circle back around to include the data of the connecting table. I need to select columns DivisionName, ProgramName, ProgramChairFName, ProgramChairLName, CourseID, OutcomeDescription from the listed tables.
SQL Diagram
The 'dead-ends' aren't really dead-ends. When you join all the tables by the appropriate keys, you'll get an assembly of the information you want.
Consider a really simple example:
table person
id name
1 Alice
table pet
id person_id animal
1 1 cat
table hobby
id person_id activity
1 1 dancing
Here, the two tables pet and hobby link to the person table via the person_id key.
In your thinking, "pet" could be considered a "dead-end" because it doesn't link to hobby. But it doesn't need to. The query:
SELECT name, animal, activity
FROM person
JOIN pet ON person.id = pet.person_id
JOIN hobby ON person.id = hobby.person_id;
creates the correct joins back to the person table. It's not a linear path (person -> pet -> hobby). The nature of the joins are specified by the "ON" part of the query. You can see this simple example works here: http://sqlfiddle.com/#!9/02c94b/1
So, in your case, you can have a series of JOINs:
SELECT [all the columns you want]
FROM Division d JOIN Program p
ON d.DivisionKey = p.DivisionKey
JOIN ProgramChairMap pcm
ON p.ProgramKey = pcm.ProgramKey
JOIN ProgramChair pc
ON pcm.ProgramChairKey = pc.ProgramChairKey
JOIN Course c
ON p.ProgramKey = c.ProgramKey
JOIN CourseOutcome co
ON c.CourseKey = co.CourseKey
JOIN Outcome o
ON co.OutsomeKey = o.OutcomeKey

How to Select foreign key names instead of number in SQL Server

I have the following situation:
One table called cad (id, name, gender, age, fok_professional, fok_agegroup, fok_ativity) and other table called professional (id, name), agegroup (id, desc),
ativity (id, name);
How to select the name value instead number as generally is presented in simple query: For exemple:
SELECT * FROM cad
output is:
id -> 1;
name -> Teste;
gender -> Male;
age -> 22;
fok_professional -> 1;
fok_agegroup -> 4;
fok_ativity -> 2;
instead I would like:
id -> 1;
name -> Teste;
gender -> Male;
age -> 22;
fok_professional -> Administrator;
fok_agegroup -> Age 19 55;
fok_ativity -> Testestetstats;
How to get the values name ?
You want something like this, using SQL JOINs to connect the tables together :
SELECT
cad.id, cad.name, cad.gender, cad.age,
professional.name,
agegroup.desc,
ativity.name
FROM cad INNER JOIN professional ON cad.fok_professional = professional.id
INNER JOIN agegroup ON cad.fok_agegroup = agegroup.id
INNER JOIN ativity ON cad.fok_ativity = ativity.id
You need to use the JOIN statement on tables cad, professionnal, agegroup and activity ON fok_XXX=XXX.id
Assuming you have appropriate permissions on the database that those tables belong to, if you want to be able to be able to just call something as simple as SELECT * FROM sometable to produce that sort of output, you may want to consider creating a view, then joining the two other tables that contain the human-readable rows in your view query.
Luckily for you, SQL Server Management Studio has a simple view designer which can help you in this regard. To access it, expand the database you want to create the view for in the Object Explorer, right-click Views, then click New View. Once you add the three tables you need into the View Designer, it will automatically create the required joins for you, assuming the relationships on each table are set up properly.
If you don't have SSMS, or you're not sure what views are, or why they're useful for your particular situation, you should review the SQL Views topic on TechNet. If you're not sure what joins are, or why tabular relationships are important, then you should consider brushing up on relational database theory a bit.
You need to use inner join between those three tables.
Try this:
SELECT C.ID,
C.NAME,
C.GENDER,
C.AGE,
P.NAME AS [FOK_PROFESSIONAL],
A.DESC AS [FOK_AGEGROUP],
AT.NAME AS [FOK_ATIVITY]
FROM CAD C
INNER JOIN PROFESSIONAL P
ON C.FOK_PROFESSIONAL = P.ID
INNER JOIN AGEGROUP A
ON C.FOK_AGEGROUP = A.ID
INNER JOIN ATIVITY AT
ON C.FOK_ATIVITY = AT.ID
You could use above solutions or you can use the following known as Common Table Expressions (CTEs) for more readability.
WITH C AS
(
SELECT
CAD.id, CAD.name, CAD.gender, CAD.age,
PRO.name,
AG.desc,
AT.name
FROM CAD INNER JOIN professional As PRO ON CAD.fok_professional = PRO.id
INNER JOIN agegroup As AG ON CAD.fok_agegroup = AG.id
INNER JOIN ativity As AT ON CAD.fok_ativity = AT.id
)
SELECT * FROM C;

SQL Join ON field differences

I have a question regarding the use of JOINS from SQL:
What's the difference between:
Select * From Employees E
JOIN Products P ON E.idEmployee = P.idEmployee
JOIN ProductsDetails PD ON P.idProduct = PD.idProduct
AND
Select * From Employees E
JOIN Products P ON P.idEmployee = E.idEmployee
JOIN ProductsDetails PD ON PD.idProduct = P.idProduct
Also, what's the difference between:
Select * From Employees E
JOIN Products P ON E.idemployee =P.idemployee
Where P.name like '%prod01%'
AND
Select * From Employees E
JOIN Products P ON E.idemployee =P.idemployee
Where E.ProdName like '%prod01%' //considering the fact that the field ProdName also exists in the table Products.
Actually, how does a query actually works, I mean the workflow:
Select * From Employees E
JOIN Products P ON E.idemployee = P.idEmployee
JOIN ProductsDetails PD ON P.idProduct = PD.idProduct
JOIN OtherTable OT ON E.idField = OT.idField
where E.ProductNumber = 1 and OT.idOfAnotherField = value
How does the where condition on the Join clauses affects the main query, how does the query actually works , what it brings first and how does it applies the conditions?
This is a bit long for a comment.
SQL is a descriptive language not a procedural language. That is, a select statement describes the results produced by processing the data, but not the methods used to achieve it. Two important parts of the database engine are the optimizer which determines how the query will be executed and the execution engine which actually executes it.
From the perspective of the optimizer, col1 = col2 and col2 = col1 are the same. So, there is no difference in the first two queries. From the perspective of what the query does, the two examples with name are the same. Or, at least, superficially the same. The two product columns could have different collations set, which would affect the meaning.
As for your final question, you need to look at your database documentation. Specifics on the execution are highly database dependent. You should also learn about explain and execution plans.
There is no Difference between the first two queries, you just providing the criteria of joining the two tables, so Table1.FieldName = Table2.FieldName is the same of Table2.FieldName = Table1.FieldName.
The Difference between the second two queries is in the first one you searching for product name in the product table, and the second in the Employee table.
If there a product With name like '%prod01%' in the product table then the first query will return it and the second will not, and if there a product with name like '%prod01%' in the employee table the second query will return value and the first will not.
The query start by building the join, starting by select the Employee table then join the values of Employee table and Product table where the idemployee equal idEmployee and do the same with Products and ProductsDetails table and ProductsDetails table and OtherTable at the end the query filter the result based on the ProductNumber of Employee Table and idOfAnotherFields of OtherTable.

SQL join tables without common key

New to SQL. I'm working with AdventureWorks 2012 trying to familiarize myself with SQL server. Having trouble joining tables that don't share a common key. Can this be done?
If you're familiar with the AdventureWorks DB I'm trying to return the Name (FirstName, MIddleName, LastName), AddressType, and Address (Combination of AddressLine1, Address Line2, City, State, PostalCode) but that draws from 3 different tables and they don't share any key that can link them together.
If the two tables does not share any common key, make sure a third table exits that acts as bridge between those two table.
For Example, Table A, and Table C may not have any common key. But in a database, it will be possible to have third table Table B which can able to join with Table A as well as Table C. So using the Table B you can bring together table A and Table C (Logically by the way it is designed).
They may not have a direct key but they are related: You have to learn how to navigate the foreign keys to use the model as it was intended. Have a look at this diagram of the AdventureWorks data model that ships with SQL 2008. In particular pay attention to the Person section (in a sort of beige colour near the centre).
Person is linked to address by way of BusinessEntity and BusinessEntityAddress therefore your query needs to join these tables to get the info you want. So, your query will look a bit like this:
SELECT .pFirstName, p.MiddleName, P.LastName, at.[Name], a.AddressLine1, a.AddressLine2, a.City, a.State, a.PostalCode
FROM Person p
INNER JOIN BusinessEntity be
ON be.BusinessEntityId = p.BusinessEntityId
INNER JOIN BusinessEntityAddress bea
ON bea.BusinessEntityId = be.BusinessEntityId
INNER JOIN AddressType at
ON at.AddressTypeId = bea.AddressTypeId
INNER JOIN Address a
ON a.AddressId = bea.AddressId
I don't have AdventureWorks to hand to test it but that should give you the basic idea. You have to follow the keys otherwise you won't get the data you want or expect.
Try something like this:
select t1.firstname, t1.middlename, t1.lastnme,
t2.addresstype,
t3.addresslin1, t3.addresslin2, t3.city
from table1 t1, table2 t2, table3 t3;
select <fields list> from table1
union all
select <the same fields list> from table2
union all
select <the same fields list> from table3
Join them with UNION ALL (or you can use UNION if you should skip duplicates)

SQL need most efficient way to select items list with sublists?

Lets look at some very simple example, have 3 tables:
dbo.Person(PersonId, Name, Surname)
dbo.Pet(PetId, Name, Breed)
dbo.PersonPet(PersonPetId, PersonId, PetId)
Need to select all persons with theirs pets if person has any.... for ex. in final application it should look smth like:
whats the most efficient way:
Select all persons and then in data access layer fill each person pets list with separate select?
Use join in sql level and then in data access layer filter all persons duplicates, by adding only one to result list and from other just filling pet list?
any other ideas?
The most efficient way is to select them all at once:
select p.*, pt.*
from Person p
left outer join PersonPet pp on p.PersonId = pp.PersonId
left outer join Pet pt on pp.PetId = pt.PetId
Need to select all persons with theirs pets if person has any...
Use:
SELECT per.name,
per.surname,
pt.name
FROM dbo.PERSON per
LEFT JOIN dbo.PERSONPET perpet ON perpet.personid = per.personid
JOIN dbo.PETS pt ON pt.petid = perpet.petid
Personally I would do it as a stored proc on the sql server. Whichever way you do it though, for display purposes you're going to have to filter out the duplicate Name and Surname.
The majority of the time taken to retrieve records is spent setting up and tearing down a query to the database. It doesn't make much difference how much data or how many tables you use in the query. It will be much more efficient to use a single query to get all the data. If your data access layer fetches each separately you'll get poor speed. Definitely use a join.
If your client and back end support multiple result sets you could also do somthing like (assuming its MSSQL)
Create Proc usp_GetPeopleAndPets
AS
BEGIN
SELECT PersonId, Name, Surname
FROM
dbo.Person p;
SELECT
pp.PersonID,
p.PetId, p.Name, p.Breed
FROM
dbo.PersonPet pp
INNER JOIN dbo.Pet p
ON pp.PetId = p.PetId
Order BY pp.PersonId
END
The data retrieval time would be roughly equivalent since its one trip to the DB. Some clients support relationships between results which allow you to do something like
Person.GetPets() or Pet.GetPerson()
The main advantage to this approach is that if you're working with people you don't have to worry about the "filter[ing] all person duplicate[s]"