Possible on UNION ALL - sql-server

I have a master table with USER and COMPANY called USER1, which maps a user to a company that the user can access and I have another master table that has a list of all available companies called COMPANY1. If a User is assigned '' company in USER1 table then it means that the user can access all companies in the COMPANY1 table.
USER1 table
User | Company
username1 | MyCompany2
username2 | MyCompany1
username3 |
username4 |
COMPANY1 table
Index | Company
1 | MyCompany1
2 | MyCompany2
3 | MyCompany3
4 | MyCompany4
Is there any way for me to do a UNION ALL to get the following:
NEW table
User | Company
username1 | MyCompany2
username2 | MyCompany1
username3 | MyCompany1
username3 | MyCompany2
username3 | MyCompany3
username3 | MyCompany4
username4 | MyCompany1
username4 | MyCompany2
username4 | MyCompany3
username4 | MyCompany4
I would really appreciate any input on this matter. :)
I tried something like
SELECT [User], [Company Name] FROM [USER1]
WHERE [Company Name] <> ''
UNION ALL
SELECT [User],
(SELECT [Company] FROM [COMPANY1]) [Company Name]
FROM [USER1]
WHERE [Company Name] = ''
Obviously this gave me an error that I can only have one result. :( How do I loop through one table like the COMPANY1 table based on the result of another table like USER1.
Thanks.

You can use CROSS JOIN of the Company1 table to the users with the user's assigned company of '' and this will produce one row for each user and each company pair, and will allow for your UNION ALL, like so:
SELECT [User], [Company Name]
FROM [USER1]
WHERE [Company Name] <> ''
UNION ALL
SELECT u.[User], c.[Company] as [Company Name]
FROM [USER1] as u
CROSS JOIN [Company1] as c
WHERE u.[Company Name] = ''
Documentation with examples for CROSS JOIN : sql-cross-join-with-examples

Related

MS-SQL Query to show max value in list of duplicates

The scenario is that I have an access table that contains rows of data for users access, and it also contains an Access Level which has either a 1 or a 2. The 1 denotes 'User' and 2 for 'Admin'. The problem is though that a user can contain both of those values (Access source coming from a variety of other systems that feed into this table).
Therefore, my problem is, how do I write a query that will return a list of users and their access level, where it ONLY shows the max value that the user has for a given Department?
Username | Department | AccessLevel
---------------------------------------------
John Smith | IT | 1
John Smith | IT | 2
John Smith | Security | 2
Sally Harris | Security | 1
Craig Larry | IT | 1
As you can see the table contains two records from John Smith, with the second having a higher access level.
The results I would like would be
John Smith | IT | 2
John Smith | Security | 2
Sally Harris | Security | 1
Craig Larry | IT | 1
This is what I have tried:
Select DISTINCT(Username), Department, MAX(AccessLevel )
From departmentaccess
Group By Username, Department, AccessLevel
The results I get back are exactly as what is in the table. I believe this query I am trying returns the Max record for rows that are entirely duplicate.
What can I do to improve this to get only my expected results?
You should remove group by AccessLevel
Select Username, Department, MAX(AccessLevel )
From departmentaccess
Group By Username, Department
You are on the right track, but you should be aggregating only by username and department:
SELECT Username, Department, MAX(AccessLevel)
FROM departmentaccess
GROUP BY Username, Department;
A more general query which would work if there were more columns in the table which did not appear in the GROUP BY clause would be:
SELECT TOP 1 WITH TIES Username, Department, AccessLevel, other_column
FROM departmentaccess
ORDER BY ROW_NUMBER() OVER (PARTITION BY Username, Department ORDER BY AccessLevel DESC);

Drupal users by role - sql query

I need a sql query count list of how many users have more than one role (by role and by role combination) eg:
admin, author: 50
admin, author, annoymouse user, authenticated user: 20
members, authenticated user: 100
etc
Thank you
MySQL query is:
mysql> SELECT ur.rid, r.name, count(*) as TOT from users_roles ur INNER JOIN role r ON r.rid = ur.rid group by ur.rid ;
+-----+---------------+-----+
| rid | name | TOT |
+-----+---------------+-----+
| 3 | administrator | 2 |
| 4 | tst | 1 |
+-----+---------------+-----+
2 rows in set (0,00 sec)
As alternative option, you have the Views Module. Create a new view, type: user. Enable and play with aggregation on the Role field

Condensing Row Data into a View

I have data in my PeopleInfo table where there are some people that have multiple records that I am trying to combine together into one record for a view.
All people data is the almost the same except for the PlanId and PlanName. So:
| FirstName | LastName | SSN | PlanId | PlanName | Status | Price1 | Price2 |
|-----------|----------|-----------|--------|----------|-----------|---------|--------|
| John | Doe | 123456789 | 1 | Plan A | Primary | 9.00 | NULL |
|-----------|----------|-----------|--------|----------|-----------|---------|--------|
| John | Doe | 123456789 | 2 | Plan B | Secondary | NULL | 5.00 |
I would like to only to have one John Doe record in my view that looked like this:
| FirstName | LastName | SSN | PlanId | PlanName | Status | Price1 | Price2 |
|-----------|----------|-----------|--------|----------|-----------|---------|--------|
| John | Doe | 123456789 | 1 | Plan A | Primary | 9.00 | 5.00 |
Where the Primary status determines which PlanId and PlanName to show. Can anyone help me with this query?
declare #t table ( FNAME varchar(10), LNAME varchar(10), SSN varchar(10), PLANID INT,PLANNAME varchar(10),stat varchar(10),Price1 decimal(18,2),Price2 decimal(18,2))
insert into #t (FNAME,LNAME,SSN,PLANID,PLANNAME,stat,Price1,Price2)values ('john','doe','12345',1,'PlanA','primary',9.00,NULL),('john','doe','12345',1,'PlanB','secondary',Null,8.00)
select
FNAME,
LNAME,
SSN,
MAX(PLANID)PLANID,
MIN(PLANNAME)PLANNAME,
MIN(stat)stat,
MIN(Price1)Price1,
MIN(Price2)Price2 from #t
GROUP BY FNAME,LNAME,SSN
(I can't yet add a comment, so have an answer.)
The only thing that troubles me here is that i am also determining which PlanId and PlanName since they are different and i want to show a specific one based off of the Status field of both records.
Then you don't even need GROUPing. It would be much simpler. Just SELECT WHERE 'Primary' = PlanName. Assuming that (A) there will always be this PlanName for each user, and (B) You are happy to ignore all others.
P.S. If you will only be using Primary and Secondary PlanNames, you might want to change the column to a bit named something like isPrimaryPlan where 1 indicates true and 0 false. However, if you might bring in e.g. Bronze and Consolation Prize Plans later, then you'll need to retain a more variable datatype. Perhaps store the plans in a separate table and have an int FOREIGN KEY to it... I could go on!
OK, I'm back after having a sleep, which has improved my brain slightly,
First, let the record reflect that I don't like the database design here. The People and Plans should be separate tables, linked by foreign keys - via a 3rd table, e.g. PeoplePlans. That takes me to another point: the people here have no primary key (at least not that you have specified). So when writing the below, I had to pick the SSN, assuming that will always be present and unique.
Anyway, something like this should work, with the caveat that I'm not going to replicate the database structure to test it.
select
FirstName,
LastName,
SSN,
PlanId,
PlanName,
Status,
_ca._sum_Price1,
_ca._sum_Price2
from
PeopleInfo as _Primary
cross apply (
select
sum(Price1) as _sum_Price1,
sum(Price2) as _sum_Price2
from
PeopleInfo
where
_Primary.SSN = SSN
) as _ca
where
'Primary' = Status;
This SELECTs all People with Primary status in order to get you those rows. It then CROSS APPLYs their Primary and any other rows and takes the summed Prices.
Hopefully this makes sense. If not, you'll have to do some reading about CROSS APPLY, in addition to about good relational database design. ;-)

SSIS Flat File Source Row Restructure

I have a flat file source of thousands of records (> 100K in some cases). This source is externally procured, and I cannot request a layout revision.
In this flat file, each row contains four columns:
| User ID | Status_1 | Status_2 | Status_3
| 1337 | Green | Yellow | Red
| 1234 | Red | Red | Green
The destination table was designed to accept two columns:
| User ID | Status Codes
| 1337 | Green
| 1337 | Yellow
| 1337 | Red
| 1234 | Red
| 1234 | Red
| 1234 | Green
Until now, I have been running 3 different SSIS packages to my destination table, one for each Status Column in the Flat File.
What I would like is to use a single SSIS package, and create either another Flat File Destination or Temp Table to mirror the destination table, and import from there.
Is this achievable? If so, what are the best practice Tasks to use, rather than simply UPDATE & SET to the Temp Table.
heh looks like a case for good ole SQL. I would use an UNPIVOT on this one.
http://technet.microsoft.com/en-us/library/ms177410(v=sql.105).aspx
That link has a great example which looks very similar to your data:
--Create the table and insert values as portrayed in the previous example.
CREATE TABLE pvt (VendorID int, Emp1 int, Emp2 int,
Emp3 int, Emp4 int, Emp5 int);
GO
INSERT INTO pvt VALUES (1,4,3,5,4,4);
INSERT INTO pvt VALUES (2,4,1,5,5,5);
INSERT INTO pvt VALUES (3,4,3,5,4,4);
INSERT INTO pvt VALUES (4,4,2,5,5,4);
INSERT INTO pvt VALUES (5,5,1,5,5,5);
GO
--Unpivot the table.
SELECT VendorID, Employee, Orders
FROM
(SELECT VendorID, Emp1, Emp2, Emp3, Emp4, Emp5
FROM pvt) p
UNPIVOT
(Orders FOR Employee IN
(Emp1, Emp2, Emp3, Emp4, Emp5)
)AS unpvt;
GO
Back when I was data warehousing, half my job seemed like it was using UNPIVOT on crap data I got through spreadsheets.

CakePHP find with 2 HABTM relationships

I'm working on project that run on CakePHP 2 framework. In this application I have:
models:
Wallnote, User, Group
relationships:
Group HABTM User
Wallnote HABTM User
Wallnote HABTM Group
tables:
wallnotes
- id
- user_id (owner id)
- ...
users_wallnotes
- user_id
- wallnote_id
groups_wallnotes
- group_id
- wallnote_id
groups_users
- group_id
- user_id
I'm using the relationships "Wallnote HABTM User" and "Wallnote HABTM Group" as a filter i.e. user_id/group_id(6) wallnote_id(10) mean, that wallnote with id 10 will be visible for user with id 6, respectively for all users in group with id 6.
I would like to find all wallnotes matching these conditions:
logged user is an owner of this wallnote OR
wallnote was shared with logged user -> record in table users_wallnotes OR
wallnote was shared with some group and logged user is member of this group
It is possible to do this using find() function?
Thanks for answer.
You have two roles: group and user.
it's very difficult to handle it with User and Group separately...
I think the standard way is you have unique role for each user and group, for handling this you must have this tables:
wallnotes
- id
- user_id (owner id)
- ...
roles
- id
- user_id
- group_id
(each rows in this table have group_id or user_id , no both of them)
roles_wallnotes
- id
- role_id
- wallnote_id
when you create a user(or group) you must create a role for it. So all groups and users, now have unique id.
for example you have 2 groups(with 1,2 ids) and 4 users(with 1,2,3,4 ids), then:
users :
|id|name |
---|------
1 | user1
2 | user2
3 | user3
4 | user4
groups :
|id|name |
---|------
1 | group1
2 | group2
roles :
|id| user_id | group_id |
---|---------|----------|
1 | 1 | null |
2 | 2 | null |
3 | 3 | null |
4 | 4 | null |
5 | null | 1 |
6 | null | 2 |
now you must have this relations:
Role hasOne Group
Role hasOne User
Wallnote HABTM Role
with this solution you can easily use find function for retrieve your data you need...

Resources