Pivot without number gets null - sql

I've tried writing a simple pivot function with SQL. My main problem is that all the tables involved have no numbers in them. I think that this is the main reason I get only one result and the rest is NULL even though some of the cells have data in them.
This is my function:
SELECT Inspector, ShiftManager, ForkliftOperator, CalibrationOperator, sorted
FROM (SELECT LHAPP_OWNER.dbo.Personnel.FirstName + ' ' + LHAPP_OWNER.dbo.Personnel.LastName
AS name, LHAPP_OWNER.dbo.PersonnelGroup.PersonnelGroup
FROM MachineGroup
INNER JOIN _MG_CurrentEmployee ON MachineGroup.MachineGroupID = _MG_CurrentEmployee.MachineGroupID
INNER JOIN LHAPP_OWNER.dbo.PersonnelGroup ON _MG_CurrentEmployee.PerssonelGroupID = LHAPP_OWNER.dbo.PersonnelGroup.PersonnelGroupID
LEFT OUTER JOIN LHAPP_OWNER.dbo.Personnel ON _MG_CurrentEmployee.PerssonelID = LHAPP_OWNER.dbo.Personnel.PersonnelID
WHERE (MachineGroup.MachineGroup = N'Line 1')) tbl PIVOT
( MIN(name) FOR PersonnelGroup IN (Inspector, ShiftManager, ForkliftOperator, CalibrationOperator, sorted) ) tbl2
I didn't know what to do with the name so I just gave it MIN. I know it's probably wrong.
Could someone give me a hand here?
My main Table of the inner select looks like this:
name || PersonnelGroup
---------------------------------------
ron roni || Inspector
Lighthouse Systems || Shift Manager
gali logi || Forklift Operator
NULL || Calibration Operator
NULL || sorted
After the function I get this:
Inspector|ShiftManager|ForkliftOperator|CalibrationOperator|Sorted
------------------------------------------------------------------------
ron roni | NULL | NULL | NULL | NULL

It's OK now. I found out the problem. Some of the PersonnelGroup names had two words in them and I looked for one word combining the tow words and so it didn't find any answers. For example, I changed 'ShiftManager' into '[Shift Manager]'

Related

How to Group_Concat with a 3-table JOIN for genealogy

I am failing to grasp how I can get the following outcome. I thought perhaps via GROUP_CONCAT, but I am also joining on 3 tables, and unclear on the correct syntax or if this is even the best approach.
Generic table layout:
Table Users: user_id | first | last
Table Orgs org_id | org_name
Table Relationship user_id | org_id | start_year | end_year
The relationship table has MANY entries, that may be associated with that specific user_id.
I need to get the User columns: id, first, last. I'd like to try and group the org data into 1 concatenated, delimited field. Maybe a double group_concatenation is needed? Which would consist of the org_id, org_name, start_year & end_year for all records in the relationship table that match the user_id. I'm hoping for an output like this:
Each '|' represents a new column/piece of data.
If there was only 1 org_id associated with the user_id, the output would be (similar) to:
user_id | first | last | org_id-org_name-start_year-end_year
If there were more than 1 org found/associated with that user_id, the output would have more concatenated/delimited data in the same column:
user_id | first | last | org_id-org_name-start_year-end_year^org_id-org_name-start_year-end_year^org_id-org_name-start_year-end_year
(Notice the '-' delimiter between values and the '^' delimiter between new 'org-grouped' data.)
When I grab that data, I can then just break it up (on the backend/PHP side of things) into an array or whatever.
I'm not sure how I can GROUP_CONCAT (if that is even the best approach here?) while I have to JOIN on 3 separate tables.
This is not my REAL query. (I'm not sure if I should post it, as I do not want to cause any confusion as it does NOT match my dummy table/column names.)
I just wanted to show my attempt that gets me 3 individual rows, (using my JOINS) but no GROUP_CONCAT stuff:
SELECT genealogy_users.imis_id, genealogy_users.full_name,
genealogy_users.member_email, genealogy_orgs.org_id,
genealogy_orgs.org_name, genealogy_relations.user_id,
genealogy_relations.relation_type, genealogy_relations.start_year,
genealogy_relations.end_year
FROM genealogy_users
INNER JOIN genealogy_relations ON genealogy_users.imis_id = genealogy_relations.user_id
INNER JOIN genealogy_orgs ON genealogy_relations.org_id = genealogy_orgs.org_id
WHERE genealogy_users.imis_id = '00003';
UPDATE:
Well I seemed to have fudged my way through it. But I'm not sure how legit this is.
Its -ALMOST- there. I believe I still need a JOIN or something? Since the genealogy_orgs.org_id = '84864' is hardcoded, and it should NOT be. Maybe it needs to come from a JOIN or something?
SELECT genealogy_users.*,
(SELECT GROUP_CONCAT(org_id,'-',
(SELECT org_name FROM genealogy_orgs WHERE genealogy_orgs.org_id = '84864'),
'-',start_year,'-',end_year,'^')
FROM genealogy_relations WHERE genealogy_relations.user_id = genealogy_users.imis_id
) AS alumni_list
FROM genealogy_users
WHERE genealogy_users.imis_id = '00003';
UPDATE 2:
My final attempt, which I think is getting me what I need. (But it's late, and I'll check back tomorrow and look at things more closely.)
SELECT genealogy_users.imis_id, genealogy_users.full_name,
genealogy_users.member_email, genealogy_orgs.org_id,
genealogy_orgs.org_name, genealogy_relations.user_id,
genealogy_relations.relation_type, genealogy_relations.start_year,
genealogy_relations.end_year,
(SELECT GROUP_CONCAT(org_id,'-',org_name,'-',start_year,'-',end_year,'^')
FROM genealogy_relations
WHERE genealogy_relations.user_id = genealogy_users.imis_id
) AS alumni_list
FROM genealogy_users
INNER JOIN genealogy_relations ON genealogy_users.imis_id = genealogy_relations.user_id
INNER JOIN genealogy_orgs ON genealogy_relations.org_id = genealogy_orgs.org_id
WHERE genealogy_users.imis_id = '00003';
Is there anything to make note of in the above attempt? Or is there a better approach? Hopefully something easily readable so it makes sense?

Query on both component parts and aggregation

I'm using sqlite3. I'd prefer to continue using it but switching is not out of the question.
I have two tables:
card face
---- ----
id id
card_id
name
position
A card has one or more entries in face.
The canonical name of a card is the name of its faces concatenated with ' // ' in position order.
Example cards: 'Dark Ritual', a card with one face named 'Dark Ritual'. 'Research // Development', a card with two faces named 'Research' and 'Development'
How can I write a SELECT that finds the details of a card regardless of whether the search term is the canonical name or the name of one of the card's faces?
This is how far I got:
SELECT id, GROUP_CONCAT(name, ' // ')
FROM
(SELECT c.id, f.name
FROM card AS c
INNER JOIN face AS f ON c.id = f.card_id
ORDER BY f.card_id, f.position)
GROUP BY id
HAVING GROUP_CONCAT(name, ' // ') IN (?)
OR name IN (?)
This finds the card I am looking for when ? = the canonical name ('Research // Development'.) It also finds what I am looking for when I supply the name of a card with only one face ('Dark Ritual') or the second of two face names ('Development'). It does not work when I supply the first of two face names ('Research'). I know the outer query can 'see' both names because they are both present in the GROUP_CONCAT form of the name. But querying on the first face name doesn't work in the HAVING.
Can you help me understand why? Thanks!
Try this version:
HAVING SUM(CASE WHEN name IN (?) THEN 1 ELSE 0 END) > 0
Do note that parameters cannot match lists. If you want to pass in a comma delimited list, you can try:
HAVING SUM(CASE WHEN ',' || name || ',' LIKE '%,' || ? || ',%' THEN 1 ELSE 0 END) > 0

Count of how many times id occurs in table SQL regexp

Hi I have a redshift table of articles that has a field on it that can contain many accounts. So there is a one to many relationship between articles to accounts.
However I want to create a new view where it lists the partner id's in one column and in another column a count of how many times the partner id appears in the articles table.
I've attempted to do this using regex and created a new redshift view, but am getting weird results where it doesn't always build properly. So one day it will say a partner appears 15 times, then the next 17, then the next 15, when the partner id count hasn't actually changed.
Any help would be greatly appreciated.
SELECT partner_id,
COUNT(DISTINCT id)
FROM (SELECT id,
partner_ids,
SPLIT_PART(partner_ids,',',i) partner_id
FROM positron_articles a
LEFT JOIN util.seq_0_to_500 s
ON s.i < regexp_count (partner_ids,',') + 2
OR s.i = 1
WHERE i > 0
AND regexp_count (partner_ids,',') = 0
ORDER BY id)
GROUP BY 1;
Let's start with some of the more obvious things and see if we can start to glean other information.
Next GROUP BY 1 on your outer query needs to be GROUP BY partner_id.
Next you don't need an order by in your INNER query and the database engine will probably do a better job optimizing performance without it so remove ORDER BY id.
If you want your final results to be ordered then add an ORDER BY partner_id or similar clause after your group by of your OUTER query.
It looks like there are also problems with how you are splitting a partnerid from partnerids but I am not positive about that because I need to understand your view and the data it provides to know how that affects your record count for partnerid.
Next your LEFT JOIN statement on the util.seq_0_to_500 I am pretty sure you can drop off the s.i = 1 as the first condition will satisfy that as well because 2 is greater than 1. However your left join really acts more like an inner join because you then exclude any non matches from positron_articles that don't have a s.i > 0.
Oddly then your entire join and inner query gets kind of discarded because you only want articles that have no commas in their partnerids: regexp_count (partner_ids,',') = 0
I would suggest posting the code for your util.seq_0_to_500 and if you have a partner table let use know about that as well because you can probably get your answer a lot easier with that additional table depending on how regexp_count works. I suspect regex_count(partnerids,partnerid) exampleregex_count('12345,678',1234) will return greater than 0 at which point you have no choice but to split the delimited strings into another table before counting or building a new matching function.
If regex_count only matches exact between commas and you have a partner table your query could be as easy as this:
SELECT
p.partner_id
,COUNT(a.id) AS ArticlesAppearedIn
FROM
positron_articles a
LEFT JOIN PARTNERTABLE p
ON regexp_count(a.partnerids,p.partnerid) > 0
GROUP BY
p.partner_id
I will actually correct myself as I just thought of a way to join a partner table without regexp_count. So if you have a partner table this might work for you. If not you will need to split strings. It basically tests to see if the partnerid is the entire partnerids, at the beginning, in the middle, or at the end of partnerids. If one of those is met then the records is returned.
SELECT
p.partner_id
,COUNT(a.id) AS ArticlesAppearedIn
FROM
PARTNERTABLE p
INNER JOIN positron_articles a
ON
(
CASE
WHEN a.partnerids = CAST(p.partnerid AS VARCHAR(100)) THEN 1
WHEN a.partnerids LIKE p.partnerid + ',%' THEN 1
WHEN a.partnerids LIKE '%,' + p.partnerid + ',%' THEN 1
WHEN a.partnerids LIKE '%,' + p.partnerid THEN 1
ELSE 0
END
) = 1
GROUP BY
p.partner_id

Oracle Query on Comma Separated Values In a Column

I have two tables. One table is a list of access points. The other is a list of who has access to what.
It use to be a person had access to either one thing or all things. But, now that has changed. Now someone might have access to several points.
The wrench in the system is that in the column that shows what they have access to may have a single value, "ALL" for all access or a comma separated list (which is new).
I originally thought I could just do WHERE Access_To Here IN(), but I am unsure how to convert the value of Access_To to a formatted list.
I need to be able to do this as a single query since I am using it for a LOV in APEX.
So, I need some help.
The Access_Points_Table has only one column, Access_Points. Here are some example values that it might have:
CSX
CZR
XR3
NBO
QHG
The Users_List table has several columns, but the most important are User_Name, Access_To. Here are some example values that it might have:
Joe | ALL
Fred | CSX
Allen | CZR, NBO
Hank | QHG
Here is query I am currently using, but it only works if there is only a single value in the Access_To column.
SELECT DISTINCT Access_Points VALUE
FROM Access_Points_Table apt
JOIN
Users_List ul
ON (ul.wwid = 'ZZ999'
AND (ul.Access_To = 'ALL' OR apt.symbol_name = ul.Access_To))
ORDER BY name ASC
What I am trying to accomplish is:
SELECT DISTINCT Access_Points VALUE
FROM Access_Points_Table apt
JOIN
Users_List ul
ON (ul.wwid = 'ZZ999'
AND (ul.Access_To = 'ALL' OR apt.symbol_name IN(Something Goes Here)))
ORDER BY name ASC
So, if run a query for the user Allen, it will return the rows:
CZR
NBO
Depending on the length of your comma-delimited data, you can use Oracle's regular expression engine (the difficulty is that Oracle limits regular expressions to 512 bytes):
SELECT DISTINCT Access_Points VALUE
FROM Access_Points_Table apt
JOIN Users_List ul
ON ( ul.wwid = 'ZZ999'
AND ( ul.Access_To = 'ALL'
OR REGEXP_LIKE(apt.symbol_name, '^(' || REPLACE(ul.Access_To, ',', '|') || ')$') ) )
ORDER BY name ASC
Alternately you can use LIKE:
SELECT DISTINCT Access_Points VALUE
FROM Access_Points_Table apt
JOIN Users_List ul
ON ( ul.wwid = 'ZZ999'
AND ( ul.Access_To = 'ALL'
OR ',' || ul.Access_To || ',' LIKE '%,' || apt.symbol_name || ',%' ) )
ORDER BY name ASC
Note that if Access_To has spaces after its commas as in your OP, it does add some complexity but that can be overcome, simply REPLACE(ul.Access_To, ' ').
By the way, I do wonder why this: ul.wwid = 'ZZ999' is in the ON clause instead of in a WHERE clause.
Another way would be to use the instr test:
SELECT DISTINCT access_points VALUE
FROM access_points_table a
JOIN users_list u
ON ( INSTR(u.access_to,a.access_points,1) > 0 )
ORDER BY 1

SQL query with check in another table

I have two tables:
TOOLS ( id | name | qt), which is a list of all equipment
TOOLSOUT ( idtools | qt ), which is a list of all the equipment that are beyond
I want to show all equipment with the quantities available.
If the TOOLS.id is not present in TOOLSOUT.idtools print qt normally. If the TOOLS.id is present in TOOLSOUT.idtools print (TOOLS.qt - TOOLS.qt)
How can I write this query?
Try this query. Seems that's what you're looking for.
SELECT
CASE
WHEN t2.idtools IS NULL
THEN t.qt
ELSE t.qt - t2.qt
END AS qt
FROM
TOOLS t
LEFT JOIN TOOLSOUT t2 ON t.id = t2.idtools