I prefer to aggregate sub query results as a JSON array in PostgreSQL.
This is an example.
SELECT
a.name,
(
SELECT json_agg(json_build_object('col1', b.col1)) AS data
FROM table_b AS b WHERE b.year = a.year
) AS data
FROM
table_a AS a
How can I do the same thing in Redshift?
As I expect you know redshift is based on Postgres 8 and does not have these functions. I can think of 2 ways you may want to proceed. 1) write a python app to connect to Redshift natively and use the python libraries to build the JSON output you desire. This could be the right way to go if the JSONs are complex and/or if the reader of the JSON is some automation. You should be able to make a stored procedure out of this python. Or 2) use list_agg() to generate the JSON string your are looking for. This route is fairly straight forward and should work ok for simple JSON constructs. You can also code this up in a stored procedure if you like.
#2 looks something like (untested):
SELECT '[' || list_agg('{"col1": "' || col1 || '"}', ', ') || ']' FROM ...
Related
The unicode() function in SQLite just accepts one parameter; if I execute this query:
select unicode(text) from table
and suppose the table has just 1 row which is abc; then the result would be: 97 which is the numeric unicode code for just a character; what if I want to get the numeric unicode code for all characters in the result of the query? Is such a thing possible within SQLite?
(I know that I can get the numerical codes out of SQLite within the environment of a programming language; I'm just curious if such a thing is possible with a SQL command within SQLite or not.)
SQLite does not really have looping constructs; doing this in the programming language would be much easier.
In SQLite 3.8.3 or later, you could use a recursive common table expression:
WITH RECURSIVE
all_chars(id, u, rest) AS (
SELECT id, unicode(text), substr(text, 2)
FROM MyTable
UNION ALL
SELECT id, unicode(rest), substr(rest, 2)
FROM all_chars
WHERE rest <> ''),
unicodes(id, list) AS (
SELECT id, group_concat(u)
FROM all_chars
GROUP BY id)
SELECT * FROM unicodes
The ID is required to merge the values of a single source row back together; doing this for a single, specific row in MyTable would be easier.
I am new to DB2 Express-C and am wondering if a SQL statement can be run in DB2 that can go thru all tables and change (could be scramble, replace, random, whatever) any 10-dgit phone numbers found. In a nut shell, do a global search and replace on all fields, in all tables, to obfuscate any phone numbers (private info).
I need to hand off a client's DB2 database (17 tables) to a software vendor to do some reporting but I have been tasked with making sure NO real phone numbers get exposed in the process. I'm sure there is a SQL statement that could handle a single table (then I could go into DB2 Control Center and run it 17x) but I am looking for a quick, clean way to 'prep' this DB before sending it out.
Thanks in advance to you DB2 gurus!
Mike
If you want to hide information in db2, you should use these functions:
ENCRYPT
DECRYPT_BIN
DECRYPT_CHAR
GETHINT
Or the IBM Database Encryption Expert
The functions are for varchar, and I think you have a int column, so it does not work.
However, you can hide all telephone numbers from different tables by applying a UDF, and querying the catalog.
For example, your UDF (user defined function) could mutiply the telephone by a given number that you only know. Then, in order to decrypt it, you just have to divide by the same number.
Then, to apply this procedure to all tables, you have to query the catalog. For example,
select tabschema, tabname
from syscat.columns
where colname like 'PHONE%'
Once, you are sure of the tables, you could update them with your UDF
select 'update ' || trim(tabschema) || '.' || trim(tabname) || ' set ' || trim(colname) || ' = myUDF(' || colname || ', 5) ;' from syscat.columns where colname like 'PHONE%'
Let's say 5 is your encryption number.
You just have to execute the output in order to hide the telephones.
I want to export ONLY the sequences created in a Database created in PostgreSQL.
There is any option to do that?
Thank you!
You could write a query to generate a script that will create your existing sequence objects by querying this information schema view.
select *
from information_schema.sequences;
Something like this.
SELECT 'CREATE SEQUENCE ' || sequence_name || ' START ' || start_value || ';'
from information_schema.sequences;
I know its too old but today I had similar requirement so I tried to solve it the same way by creating a series of "CREATE SEQUENCE" queries which can be used to RE-create sequences on the other DB with bad import (missing sequences)
here is the SQL I used:
SELECT
'CREATE SEQUENCE '||c.relname||
' START '||(select setval(c.relname::text, nextval(c.relname::text)-1))
AS "CREATE SEQUENCE SQLs"
FROM
pg_class c
WHERE
c.relkind = 'S'
Maybe that can be helpful for someone.
Using DBeaver, you can
open a schema
select its sequences
crtl-F to search for the sequences you're interested in
crtl-A to select all of them
Right-click and select Generate SQL -> DDL
You will be given SQL statements to create all of the sequences selected.
I am looking to extract Sybase datatype for all the columns in a table. When I try to achieve this using $sth->{TYPE}, I get a numeric version of the datatype (i.e. instead of sybase datatype varchar, I get 0).
From the DBD::Sybase documentation, I noticed that SYBTYPE attribute of syb_describe function might be able to produce what I am looking for. But it seems that my understanding is not proper. SYBTYPE also prints datatype in numeric form only.
Is there any way to fetch the textual representation of actual Sybase datatype (instead of the number)?
It sounds like you wish to reverse engineer the create table definition. Here is an SQL script you can use for Sybase or SQL Server tables.
select c.name,
"type(size)"=case
when t.name in ("char", "varchar") then
t.name + "(" + rtrim(convert(char(3), c.length)) + ")"
else t.name
end,
"null"=case
when convert(bit, (c.status & 8)) = 0 then "NOT NULL"
else "NULL"
end
from syscolumns c, systypes t
where c.id = object_id("my_table_name")
and c.usertype *= t.usertype
order by c.colid
go
Note: This could still be edited with a nawk script to create a real SQL schema file.
The nawk script would strip the header, add "create table my_table_name", add commas, strip the footer and add a "go".
Good SQL, good night!
I found a workaround (Note: This does not answer the question though):
What I did was simply joined the sysobjects, systypes and syscolumns system tables.
I am writing a script using DBI to execute a select query to an Oracle db. I have successfully able to capture the data but I need help to change the output.
Below is the sample output.
Type
2
6
I want to display 2=>Good and 6=>Bad
Can anyone please suggest me the Perl code to map the output?
# Create a hash of the values you want to output
my %human_text = (2 => 'Good', 6 => 'Bad');
# and then access the hash values like this:
print $human_text{2}; #will output 'Good'
print $human_text{6}; #will output 'Bad'
Usually the easiest way is to change directly the values outputted by the SQL query. With Oracle you can use DECODE.
SELECT DECODE(MY_TYPE, 2, 'TWO', 6, 'SIX', 'DEFAULT_VALUE') FROM MY_TABLE
The standard SQL way is to use a CASE conditional expression. It is a little more verbose, but more powerful and more portable. It works for example in Oracle, PostgreSQL and MS-SQL.
SELECT
CASE
WHEN MY_TYPE = 2 THEN 'TWO'
WHEN MY_TYPE = 6 THEN 'SIX'
ELSE 'DEFAULT_VALUE'
END CASE
FROM MY_TABLE
If you still want to do it in Perl, you might create a Hash. The code sample is quite trivial, and well documented in the link I provided.
Create a lookup table in your RDBMS which maps 2 to Good and 6 to Bad. Create an INNER JOIN (or LEFT JOIN if you anticipate having values that will not match the lookup) with your SQL statement (or create a VIEW which returns the JOINed tables). Trying to use Perl or SQL SELECT statements to replace database design is probably a bad idea.
$inWords = ("","very good","good","satisfactory","sufficient","poor","bad")[$number];