Redshift: How to list all users in a group - amazon-web-services

Getting the list of users belonging to a group in Redshift seems to be a fairly common task but I don't know how to interpret BLOB in grolist field.
I am literally getting "BLOB" in grolist field from TeamSQL. Not so sure this is specific to TeamSQL but I kind of remember thatI got a list of IDs there instead previously in other tool

This worked for me:
select usename
from pg_user , pg_group
where pg_user.usesysid = ANY(pg_group.grolist) and
pg_group.groname='<YOUR_GROUP_NAME>';

SELECT usename, groname
FROM pg_user, pg_group
WHERE pg_user.usesysid = ANY(pg_group.grolist)
AND pg_group.groname in (SELECT DISTINCT pg_group.groname from pg_group);
This will provide the usernames along with the respective groups.

this worked better for me:
SELECT
pu.usename,
pg.groname
FROM
pg_user pu
left join pg_group pg
on pu.usesysid = ANY(pg.grolist)
order by pu.usename

Related

Querying Redshift Permissions via Groups

Question:
"For each user, show me the groups they belong (1) to and the tables they can query as a result of being part of that group (2)."
Details: This is on redshift.
I'm curious if anyone has done anything like this.
The first part isn't hard, I did that with this:
SELECT usename, groname
FROM pg_user,
pg_group
WHERE pg_user.usesysid = ANY (pg_group.grolist)
AND pg_group.groname in (SELECT DISTINCT pg_group.groname from pg_group)
The second part is much harder I think. Showing table permissions isn't, but that's not really what's being asked. That can be accomplished with this:
SELECT has_table_privilege(user, table, 'select'::text) as select...
But that does not show which group gives the user that permission.
Any advice is great!

Query for listing Datasets and Number of tables in Bigquery

So I'd like make a query that shows all the datasets from a project, and the number of tables in each one. My problem is with the number of tables.
Here is what I'm stuck with :
SELECT
smt.catalog_name as `Project`,
smt.schema_name as `DataSet`,
( SELECT
COUNT(*)
FROM ***DataSet***.INFORMATION_SCHEMA.TABLES
) as `nbTable`,
smt.creation_time,
smt.location
FROM
INFORMATION_SCHEMA.SCHEMATA smt
ORDER BY DataSet
The view INFORMATION_SCHEMA.SCHEMATA lists all the datasets from the project the query is executed, and the view INFORMATION_SCHEMA.TABLES lists all the tables from a given dataset.
The thing is that the view INFORMATION_SCHEMA.TABLES needs to have the dataset specified like this give the tables informations : dataset.INFORMATION_SCHEMA.TABLES
So what I need is to replace the *** DataSet*** by the one I got from the query itself (smt.schema_name).
I am not sure if I can do it with a sub query, but I don't really know how to manage to do it.
I hope I'm clear enough, thanks in advance if you can help.
You can do this using some procedural language as follows:
CREATE TEMP TABLE table_counts (dataset_id STRING, table_count INT64);
FOR record IN
(
SELECT
catalog_name as project_id,
schema_name as dataset_id
FROM `elzagales.INFORMATION_SCHEMA.SCHEMATA`
)
DO
EXECUTE IMMEDIATE
CONCAT("INSERT table_counts (dataset_id, table_count) SELECT table_schema as dataset_id, count(table_name) from ", record.dataset_id,".INFORMATION_SCHEMA.TABLES GROUP BY dataset_id");
END FOR;
SELECT * FROM table_counts;
This will return something like:

redshift - Not able to apply listagg function

I am getting error when trying to use listagg function.
Query
select
a.user_name,
listagg(a.group_name::text)
within group (order by a.group_name) as group_name
from (
SELECT
usename as user_name,
groname as group_name
FROM
pg_user
join
pg_group
on
pg_user.usesysid = ANY(pg_group.grolist) AND
pg_group.groname in (SELECT DISTINCT pg_group.groname from pg_group)
)a
group by user_name
Error
[Code: 500310, SQL State: XX000] Amazon Invalid operation: One or more of the used functions must be applied on at least one user created tables. Examples of user table only functions are LISTAGG, MEDIAN, PERCENTILE_CONT, etc;
None of the value is null.
Just like there are some functions that can only be run on the leader node there are some that can only be run on compute nodes - listagg() is one of these. If you need to run listagg() on leader data there are a few approaches you can use: (sorry I'm not on a cluster now so cannot test these directly - I saw your question was aging and thought I'd get you started. Grain of salt as I also cannot directly observe your issue but I think I've know what is going on.)
You can use a cursor to save the data from the leader node and use
this as the source for listagg(). A stored procedure can
streamline this. There are examples of this on stackoverflow.
You can make a temp table out of the leader node data and use this
in listagg() but I expect you will need to exit(unload) and
reenter(copy) the cluster to do this.
There just isn't a direct path from leader-node-only results to the compute nodes without some sort of this kind of push-up. Consequence of the large networked cluster architecture of Redshift.
UPDATE
I got some cluster time and there are several unexpected issues with this one. grolist is an array type that isn't generally support cluster wide and the need to user pg_group as source are key ones. So this is going to require #1 AND #2 from above.
The process goes like this:
Define cursor to hold the result of the pg_user / pg_group join select statement
Move cursor results to temp table
Use temp table as source to outer (list_agg()) select
A stored procedure can be written to do #1 and #2 which streamlines things. So you end up with the following SQL:
CREATE OR REPLACE procedure make_user_group()
AS
$$
DECLARE
row record;
BEGIN
create temp table user_group (user_name varchar(256),group_name varchar(256));
for row in SELECT
usename::text as user_name,
groname::text as group_name
FROM
pg_user
join
pg_group
on
pg_user.usesysid = ANY(pg_group.grolist) AND
pg_group.groname in (SELECT DISTINCT pg_group.groname from pg_group)
LOOP
INSERT INTO user_group(user_name,group_name) VALUES (row.user_name,row.group_name);
END LOOP;
END;
$$ LANGUAGE plpgsql;
call make_user_group();
select
user_name,
listagg(group_name::text, ', ')
within group (order by group_name) as group_name
from user_group
group by user_name;
Clearly the stored procedure only needs to be created once but called every time the temp table needs to be created.

Unable to join two tables from two different databases in Athena

I have 2 databases in Athena each with it's own table. I'm not sure how to join two tables.Contractinfo_2019 is a database and so is enrollmentinfo_2019 another database. I keep getting error :
"SYNTAX_ERROR: line 11:10: Table awsdatacatalog.enrollmentinfo_2019.contractinfo2019 does not exist
This query ran against the "enrollmentinfo_2019" database, unless qualified by the query. Please post the error message on our forum or contact customer support with Query Id: 1bbc3941-4fa1-40a0-87c1-eb093784c990."
SELECT a.*,
b.*
FROM
(SELECT contract_id,
plan_id,
organization_type,
plan_type,
organization_name,
plan_name,
parent_organization
FROM contractinfo2019) AS a
LEFT JOIN
(SELECT contract_number,
plan_id,
state,
county,
enrollment
FROM enrollmentinfo2019) AS b
ON a.contract_id=b.contract_number
AND a.plan_id=b.plan_id
Can someone please guide me how to join table's in Athena. I'm not sure what am i doing wrong here?
I would recommend re-writing the query using WITH
for example:
WITH a AS
(SELECT contract_id,
plan_id,
organization_type,
plan_type,
organization_name,
plan_name,
parent_organization
FROM Contractinfo_2019.contractinfo2019),
b as
(SELECT contract_number,
plan_id,
state,
county,
enrollment
FROM enrollmentinfo_2019.enrollmentinfo2019)
SELECT * FROM a
LEFT JOIN b ON a.contract_id=b.contract_number
AND a.plan_id=b.plan_id
You just need qualified table names.
Instead of:
FROM contractinfo2019
use this (assuming I got your database and table name right):
FROM contractinfo_2019.contractinfo2019

How to add multiple customers to one group on opencart at once?

Is there any way to add many customers to one group at once on opencart? Its too much of a work to add 7500 customers to different groups by one by one.
If you need to add all customers to one group while you know the group ID, you can execute this SQL query in your preferred MySQL administration tool:
INSERT INTO <DB_PREFIX>customer_to_group (customer_id, group_id)
SELECT customer_id, <GROUP_ID>
FROM <DB_PREFIX>customer
Replace <DB_PREFIX> with your DB table name prefix (or none if you are not using it).
Replace <GROUP_ID> by the numeric representation of the group you want the customers to be assigned to.
You can use a similar approach if you want to insert only few customers - but again you need to know their ID's or email addresses (i.e. some unique value that could identify each customer):
INSERT INTO <DB_PREFIX>customer_to_group (customer_id, group_id)
SELECT customer_id, <GROUP_ID>
FROM <DB_PREFIX>customer
WHERE customer_id IN (<ID1>, <ID2>, <ID3>, '<ID...>')
or
INSERT INTO <DB_PREFIX>customer_to_group (customer_id, group_id)
SELECT customer_id, <GROUP_ID>
FROM <DB_PREFIX>customer
WHERE email IN ('email#address.1', 'email#address.2', 'email#address.3', '...')
Let's say you want to assign only those customers living in USA (where the country ID is <COUNTRY_ID>):
INSERT INTO <DB_PREFIX>customer_to_group (customer_id, group_id)
SELECT c.customer_id, <GROUP_ID>
FROM <DB_PREFIX>customer c
LEFT JOIN <DB_PREFIX>customer_address ca ON ca.customer_id = c.customer_id
WHERE ca.country_id = <COUNTRY_ID>
GROUP BY c.customer_id