Can I select a list of Blob with CQL? - cql

I store all event_id in blob type and would like to select multiple event_id at once.
It works well if I send the query one by one. Like this one:
SELECT JSON event_id, user FROM demo.events WHERE customer_id=1234 AND event_id=0x123123;
But I would like to use IN clause to query multiple event_id at the same time. I've tried the following CQL but failed:
SELECT JSON event_id, user FROM demo.events WHERE customer_id=1234 AND event_id in [0x123123, 0x456456, 0x789789];
An error message is given
SyntaxException: line 1:106 no viable alternative at input 'event_id'
Can anyone tell me if it's possible to do it? Thank you.

IN operator requires tuble_literal on the right side of the expression. Tuples can be defined with (). In your case IN (x, y, z) would work:
$ create table test.a (customer_id int, event_id blob, user text, PRIMARY KEY (customer_id, event_id));
$ insert into test.a (customer_id, event_id, user) values (1, 0x123123, 'a');
$ insert into test.a (customer_id, event_id, user) values (1, 0x123124, 'a');
$ insert into test.a (customer_id, event_id, user) values (1, 0x123125, 'a');
$ SELECT JSON event_id, user FROM test.a WHERE customer_id=1 AND event_id in (0x123123, 0x123124);
[json]
---------------------------------------
{"event_id": "0x123123", "user": "a"}
{"event_id": "0x123124", "user": "b"}
(2 rows)

Related

Postgres JOIN child as JSON

I have a node server accessing a postgres database through a npm package, pg, and have a working query that returns the data, but I think it may be able to be optimized. The data model is of versions and features, one version has many feature children. This query pattern works in a few contexts for my app, but it looks clumsy. Is there a cleaner way?
SELECT
v.*,
coalesce(
(SELECT array_to_json(array_agg(row_to_json(x))) FROM (select f.* from app_feature f where f.version = v.id) x ),
'[]'
) as features FROM app_version v
CREATE TABLE app_version(
id SERIAL PRIMARY KEY,
major INT NOT NULL,
mid INT NOT NULL,
minor INT NOT NULL,
date DATE,
description VARCHAR(256),
status VARCHAR(24)
);
CREATE TABLE app_feature(
id SERIAL PRIMARY KEY,
version INT,
description VARCHAR(256),
type VARCHAR(24),
CONSTRAINT FK_app_feature_version FOREIGN KEY(version) REFERENCES app_version(id)
);
INSERT INTO app_version (major, mid, minor, date, description, status) VALUES (0,0,0, current_timestamp, 'initial test', 'PENDING');
INSERT INTO app_feature (version, description, type) VALUES (1, 'store features', 'New Feature')
INSERT INTO app_feature (version, description, type) VALUES (1, 'return features as json', 'New Feature');
The subquery in FROM clause may not be needed.
select v.*,
coalesce((select array_to_json(array_agg(row_to_json(f)))
from app_feature f
where f.version = v.id), '[]') as features
from app_version v;
And my 5 cents. Pls. note that id is primary key of app_version so it's possible to group by app_version.id only.
select v.*, coalesce(json_agg(to_json(f)), '[]') as features
from app_version v join app_feature f on f.version = v.id
group by v.id;
You could move the JSON aggregation into a view, then join to the view:
create view app_features_json
as
select af.version,
json_agg(row_to_json(af)) as features
from app_feature af
group by af.version;
The use that view in a join:
SELECT v.*,
fj.features
FROM app_version v
join app_features_json afj on afj.version = v.id

Cassandra 3.11, Filter Results by list (searching for alternatives)

I want to ask cassandra to filter its results by a list of arguments. But this is not possible on a "normal" column. Or in cassandra's words:
IN predicates on non-primary-key columns (access_right_id) is not yet supported
My table looks like this:
CREATE TABLE "service"
(
course_id uuid,
type text,
access_token uuid,
name_de text,
name_en text,
url text,
edit_right_id uuid,
access_right_id uuid,
PRIMARY KEY (course_id, type, access_token)
);
I want to execute a query like this:
SELECT * FROM service WHERE
course_id = :courseId
AND type = :type
AND access_right_id IN :rights
I am now searching for a solution to my problem. I am thinking of three possible solutions:
Send N times the query (maybe with a materialized view and access_right_id as a primary key part (clustering key))
SELECT * FROM service WHERE
course_id = :courseId
AND type = :type
AND access_right_id = :right
Send a generated query like this:
SELECT * FROM service WHERE
course_id = :courseId
AND type = :type
AND (access_right_id = :right1 OR access_right_id = :right2 OR access_right_id = :right ...)
Send a query without filtering and filter the result in code.
What do you this is best in this case? What is more cassandra "compliant"?
Thank you in advance for your input.

How to run CQL in Zeppelin by taking input in user input format?

I was trying to run CQL query by taking in user input format in Zeppelin tool:-
%cassandra
SELECT ${Select Fields Type=uuid ,uuid | created_by | email_verify| username} FROM
${Select Table=keyspace.table_name}
${WHERE email_verify="true" } ${ORDER BY='updated_date' }LIMIT ${limit = 10};
while running this query I was getting this error:
line 4:0 mismatched input 'true' expecting EOF
(SELECT uuid FROM keyspace.table_name ["true"]...)
You need to move WHERE and ORDER BY out of the dynamic form declaration.
The input field declaration is looks as following: ${field_name=default_value}. In your case, instead of WHERE ..., you've got the field name of WHERE email_verify.
It should be as following (didn't tested):
%cassandra
SELECT ${Select Fields Type=uuid ,uuid | created_by | email_verify| username} FROM
${Select Table=keyspace.table_name}
WHERE ${where_cond=email_verify='true'} ORDER BY ${order_by='updated_date'} LIMIT ${limit = 10};
Update:
here is the working example for table with following structure:
CREATE TABLE test.scala_test2 (
id int,
c int,
t text,
tm timestamp,
PRIMARY KEY (id, c)
) WITH CLUSTERING ORDER BY (c ASC)

SELECT rows with primary key of multiple columns

How do I select all relevant records according to the provided list of pairs?
table:
CREATE TABLE "users_groups" (
"user_id" INTEGER NOT NULL,
"group_id" BIGINT NOT NULL,
PRIMARY KEY (user_id, group_id),
"permissions" VARCHAR(255)
);
For example, if I have the following JavaScript array of pairs that I should get from DB
[
{user_id: 1, group_id: 19},
{user_id: 1, group_id: 11},
{user_id: 5, group_id: 19}
]
Here we see that the same user_id can be in multiple groups.
I can pass with for-loop over every array element and create the following query:
SELECT * FROM users_groups
WHERE (user_id = 1 AND group_id = 19)
OR (user_id = 1 AND group_id = 11)
OR (user_id = 5 AND group_id = 19);
But is this the best solution? Let say if the array is very long. As I know query length may get ~1GB.
what is the best and quick solution to do this?
Bill Karwin's answer will work for Postgres just as well.
However, I have made the experience that joining against a VALUES clause is very often faster than a large IN list (with hundreds if not thousands of elements):
select ug.*
from user_groups ug
join (
values (1,19), (1,11), (5,19), ...
) as l(uid, guid) on l.uid = ug.user_id and l.guid = ug.group_id;
This assumes that there are no duplicates in the values provided, otherwise the JOIN would result in duplicated rows, which the IN solution would not do.
You tagged both mysql and postgresql, so I don't know which SQL database you're really using.
MySQL at least supports tuple comparisons:
SELECT * FROM users_groups WHERE (user_id, group_id) IN ((1,19), (1,11), (5,19), ...)
This kind of predicate can be optimized in MySQL 5.7 and later. See https://dev.mysql.com/doc/refman/5.7/en/range-optimization.html#row-constructor-range-optimization
I don't know whether PostgreSQL supports this type of predicate, or if it optimizes it.

What is the correct way to insert data into a Cassandra UDT?

Here is the type I have created,
CREATE TYPE urs.dest (
destinations frozen<list<text>>);
And here is the table ,
CREATE TABLE urs.abc (
id int,
locations map<text, frozen<dest>>,
PRIMARY KEY(id));
When I try to insert values from cqlsh,
try 1:
insert into urs.abc (id, locations ) values (1, {'coffee': { 'abcd', 'efgh'}});
try 2:
insert into urs.abc (id, locations ) values (1, {'coffee': ['abcd', 'efgh']});
try 3:
insert into urs.abc (id) values (1);
update urs.abc set locations = locations + {'coffee': {'abcd','qwer'}} where id=1;
I'm getting the below error,
Error from server: code=2200 [Invalid query] message="Invalid map literal for locations: value {'abcd', 'qwer'} is not of type frozen<dest>"
Can anyone please let me know the correct way to add value to my UDT?
Table creation seems fine
To insert to the table to urs.abc use this
insert into urs.abc (id, locations ) values (1, {'coffee':{ destinations: ['abcd', 'efgh']}});
You are missing the field name destinations.

Resources