I have a table called LOGS with the following columns:
id - user - object - ref - field - from - to - join - ts
to store logging of a PHP app I am writing. However, is it possible in the SQL query when I return all the data into PHP to do a 'conditional' join? For instance the join column might contain 'people' indicating that the field column needs to be joined in relationship with the table people.
Is this possible? Or shall I have to do it on the PHP side?
A LEFT join should do the trick here
select *
from
LOGS l
left join
PEOPLE p on p.peopleid = l.field and l.join = 'people'
I'm not sure I've used the correct relationship fields between LOGS and PEOPLE but by including a clause of join where log type is people then you can see PEOPLE entries are conditionally returned.
Things become more complicated when you want to conditionally return from different tables, because you need to make sure the extra fields, brought in by the entity table are the same (or at least are identified as the same). In which case your forced to UNION results.
select
l.*,
p.peopleid as entityid,
p.fullname as displayname
from
LOGS l
left join
PEOPLE p on p.peopleid = l.field and l.join = 'people'
union all
select
l.*,
a.accountid as entityid,
p.accountname as displayname
from
LOGS l
left join
ACCOUNT a on a.accountid = l.field and l.join = 'account'
or perhaps this
select
l.*,
entity.entityid as entityid,
entity.displayname as displayname
from
LOGS l
left join
(
select 'people' as type, p.peopleid as entityid, p.fullname as displayname
from PEOPLE
union all
select 'account', a.accountid, p.accountname
from ACCOUNT
) entity on entity.type = l.join and entity.entityid = l.field
But I can imagine combining lots of your entity tables like this to return logs could make for a really slow query.
Related
i have following sql in java project:
select distinct * from drivers inner join licenses on drivers.user_id=licenses.issuer_id
inner join users on drivers.user_id=users.id
where (licenses.state='ISSUED' or drivers.status='WAITING')
and users.is_deleted=false
And result i database looks like this:
And i would like to get only one result instead of two duplicated results.
How can i do that?
Solution 1 - That's Because one of data has duplicate value write distinct keyword with only column you want like this
Select distinct id, distinct creation_date, distinct modification_date from
YourTable
Solution 2 - apply distinct only on ID and once you get id you can get all data using in query
select * from yourtable where id in (select distinct id from drivers inner join
licenses
on drivers.user_id=licenses.issuer_id
inner join users on drivers.user_id=users.id
where (licenses.state='ISSUED' or drivers.status='WAITING')
and users.is_deleted=false )
Enum fields name on select, using COALESCE for fields which value is null.
usually you dont query distinct with * (all columns), because it means if one column has the same value but the rest isn't, it will be treated as a different rows. so you have to distinct only the column you want to, then get the data
I suspect that you want left joins like this:
select *
from users u left join
drivers d
on d.user_id = u.id and d.status = 'WAITING' left join
licenses l
on d.user_id = l.issuer_id and l.state = 'ISSUED'
where u.is_deleted = false and
(d.user_id is not null or l.issuer_id is not null);
I have the following problem. I run this request, which passes successfully but it says "0 (rows affected)". In short, what I want to do. I'm trying to write a query that adds elements to the main table because I've linked Child tables I'm trying to retrieve the IDs and put them in the main table
INSERT INTO Articles
([ID],
[ArtName],
[ArtType],
[SerNo],
[MACNo],
[UserID],
[Available],
[CityID],
[StoreID],
[WorkplaceID],
[ItemPrice],
[IP_01],
[IP_02],
[Note])
SELECT
(SELECT max([ID])+1 FROM Articles),
'HP',
art.ID,
'123',
'А18Н31',
u.ID,
av.ID,
c.ID ,
s.ID,
w.ID,
'14.23',
'192.168.11.3',
'192.168.11.3',
GetDate()
FROM Articles a
INNER JOIN Workplace w ON a.WorkplaceID = w.ID
INNER JOIN Store s ON a.StoreID = s.ID
INNER JOIN City c ON a.CityID = c.ID
INNER JOIN Avaiable av ON a.Available = av.ID
INNER JOIN Users u ON a.UserID = u.ID
INNER JOIN ArtType art ON a.ArtType = art.ID
WHERE c.CityName LIKE '%Sofia%' AND art.ArtTypeName LIKE '%FirstType%' AND s.StoreName LIKE '%First%' AND av.AvaiableName LIKE '%yes%' AND u.UserName LIKE '%Valq%' AND w.WorkplaceName LIKE '%FWorkplace%'
This says "0 rows affected" because the SELECT returns no rows. This could be because nothing matches the JOINs. This could be because the WHERE clause filters out all rows. Without sample data, there is no way to tell. You have to investigate yourself.
That said, this is highly suspicious:
(SELECT max([ID])+1 FROM Articles),
This is not the right way to have an incremental id in a table. You should be using an identity column. Or perhaps default to a sequence. In either case, the value of id would be set automatically when rows are inserted.
Also note that if this inserts multiple rows, all would get the same id, which is presumably not what you want.
I have two tables. First one is name of all members and second is all projects and its team members of different roles.
Table 1 : [members] id, name
Table 2 : [projects] id, proj_name, sponsor (fk1_tbl_1), proj_mgr(fk2_tbl_1) , proj_co (fk3_tbl_1)
I created a query to show the project name and names of all project roles.
I am doing three joins with two sub-queries in order to achieve this.
I want to know if there is better ways to do this (in pure sql, NOT script languages like pl/sql).
select f.proj_name, f.proj_sponsor, f.proj_mgr, e.name proj_co
from
name e,
(
select
d.proj_name, d.proj_sponsor, c.name proj_mgr, d.proj_co
from
members c,
(
select
b.proj_name, a.name proj_sponsor, b.proj_mgr mgr, b.proj_co co
from
members a, projects b
where
b.sponsor = a.id
) d
where
c.id = d.mgr
) f
where
e.id = f.proj_co
Use join and join again:
select p.*, ms.name as sponsor, mm.name as manager, mc.name as co_name
from projects p left join
members ms
on p.sponsor = ms.id left join
members mm
on p.manager = mm.id left join
members mo
on p.proj_co = mo.id;
Notes:
This uses left join in case any values are missing. The project will still be returned.
Never use commas in the FROM clause.
Always use proper, explicit, standard JOIN syntax.
Use meaningful table aliases, rather than arbitrary letters.
So I have 3 tables which are:
Client = ClientID, ClientName,
Room = RoomID, RoomName
Booking = BookingID, RoomID, ClientID, Status (3 possible values: Booked, Checked-In, Checked-Out), CheckInDate, CheckOutDate
RoomID and ClientID has one-to-many relationship with the fields in booking table
My goal is to create a query that shows all of the rooms in the current time and show their status along with the information of the ocupant (if any) and their check in check out time of each room with these fields:
RoomStatus = RoomName, Status (4 possible values: Empty, Booked, Checked-In, Checked-Out (might be unnecessary since ocupant is no longer in the room)), ClientName, CheckInDate, CheckOutDate
I have managed to create simple query that using the relationships between the tables that shows all of the currently used room that shows all the information I needed. But the problem arise when I'm unable to show the unused room in the query. Since the status fields are in the booking table to keep it simple, the room table has no status field on its own to use.
I've attempted to make an empty query with showing all record of the room using the room id field and make new fields similar with the working ones that has null values and tried to left join and union it with the working one. However, left join only select similar record which only ends up showing the same thing as before and union provides duplicates. But I think this method to be "messy" if it does work.
So I'm open to any other method that is much better than my proposed method. Thank you very much.
I think this is what you are trying to achieve
select *
from #room c
left join
(
select b.*
from #Room r
inner join #Booking b on r.RoomID = b.RoomID
inner join #Client c on c.ClientID = b.ClientID
where CheckInDate = '02/03/2016'
) a on a.RoomID = c.RoomID
In MS Access this can be achived in 2 steps. 1st step will create Query which display result of this query.
select b.*
from #Room r
inner join #Booking b on r.RoomID = b.RoomID
inner join #Client c on c.ClientID = b.ClientID
where CheckInDate = '02/03/2016'
in second step you will do the left join on above QUERY with table rooms. Displaying All records from table room and only those records from above query where join matches.
Our application allows administrators to add “User Properties” in order for them to be able to tailor the system to match their own HR systems. For example, if your company has departments, you can define “Departments” in the Properties table and then add values that correspond to “Departments” such as “Jewelry”, “Electronics” etc… You are then able to assign a department to users.
Here is the schema:
(source: mindgravy.net)
In this schema, a User can have only one UserPropertyValue per Property, but doesn’t have to have a value for the property.
I am trying to build a query that will be used in SSRS 2005 and also have it use the PropertyValues as the filter for users. My query looks like this:
SELECT UserLogin, FirstName, LastName
FROM Users U
LEFT OUTER JOIN UserPropertyValues UPV
ON U.ID = UPV.UserID
WHERE UPV.PropertyValueID IN (1, 5)
When I run this, if the user has ANY of the property values, they are returned. What I would like to have is where this query will return users that have values BY PROPERTY.
So if PropertyValueID = 1 is of Department (Jewelry), and PropertyValueID = 5 is of EmploymentType (Full Time), I want to return all users that are in Department Jewelry that are EmployeeType of Full Time, can this be done?
Here's a full data example:
User A has Department(Jewelry value = 1) and EmploymentType(FullTime value = 5)User B has Department(Electronics value = 2) and EmploymentType(FullTime value = 5)User C has Department(Jewelry value = 1) and EmployementType(PartTime value = 6)
My query should only return User A using the above query
UPDATE:
I should state that this query is used as a dataset in SSRS, so the parameter passed to the query will be #PropertyIDs and it is defined as a multi-value parameter in SSRS.
WHERE UPV.PropertyValueID IN (#PropertyIDs)
I figured out how to get this working in a completely hacky fashion:
SELECT UserLogin, FirstName, LastName
FROM Users
LEFT OUTER JOIN
(
SELECT UserID
FROM UserPropertyValues
WHERE PropertyValueID IN (#PropertyIDs)
GROUP BY UserID
HAVING COUNT(UserID) =
(
SELECT COUNT(*) FROM
(
SELECT PropertyID FROM PropertyValues
WHERE ID IN (#PropertyIDs) GROUP BY PropertyID
) p
)
) filtered on Users.UserID = filtered.UserID
Because we can determine the number of properties used in the parameter #PropertyIDs (returned by the select count(*)), we can make sure that the users returned from the query has the same number of properties as what was passed in #PropertyIDs.
SELECT UserLogin, FirstName, LastName
FROM Users
where UserID in (
select UserID
from UserPropertyValues upv1
inner join UserPropertyValues upv2 on upv1.UserID = upv2.UserID
and upv1.PropertyValueID = 1 and upv2.PropertyValueID = 5
) a
You need to join to the key_value store individually for each property you want to get (2 properties, 2 joins, 100 properties, 100 joins), This is why it is a poor design choice for performance.
Expanding on OrbMan's answer. This is going to give you one row per user/property.
SELECT U.UserLogin, U.FirstName, U.LastName, P.Name AS PropertyName, PV.Name AS PropertyValue
FROM Users U
INNER JOIN UserPropertyValues UPV
ON U.ID = UPV.UserID
INNER JOIN Properties P
ON UPV.PropertyID = P.ID
INNER JOIN PropertyValues PV
ON UPV.PropertyID = PV.ID
where UserID in (
select UserID
from UserPropertyValues upv1
inner join UserPropertyValues upv2 on upv1.UserID = upv2.UserID
and upv1.PropertyValueID IN (#PropertyIDs))