Query limitations due to composite partition keys in cassandra? - cassandra

If i have two table structures, one with:
Let this be A,
PRIMARY KEY (measureid, statename, reportyear, countyname)
and another with, (Let this be B):
PRIMARY KEY ((measureid, statename, reportyear), countyname)
What are the query limitations of table structure B over A ?
In what queries having composite partition key will pose a problem?

In table A where:
PRIMARY KEY (measureid, statename, reportyear, countyname)
You can query the table with just measureid and it will return rows of statename. Specifically:
SELECT FROM ... WHERE measureid = ?
Alternatively, you can also query with:
SELECT FROM ... WHERE measureid = ? AND statename = ?
SELECT FROM ... WHERE measureid = ? AND statename = ? AND reportyear = ?
SELECT FROM ... WHERE measureid = ? AND statename = ? AND reportyear = ? AND countyname = ?
In table B where:
PRIMARY KEY ((measureid, statename, reportyear), countyname)
You must specify all of measureid, statename, reportyear to query the data. This will return all the rows of one partition:
SELECT FROM ... WHERE measureid = ? AND statename = ? AND reportyear = ?
To retrieve one specific row of one partition:
SELECT FROM ... WHERE measureid = ? AND statename = ? AND reportyear = ? AND countyname = ?
To be clear, you cannot query table B with the following:
SELECT FROM ... WHERE measureid = ?
SELECT FROM ... WHERE measureid = ? AND statename = ?
since you must specify the 3 columns of the partition key. I've explained why in this post https://community.datastax.com/questions/7866/. Cheers!

Related

TableAlias doesn't work with multiple joins

TableAlias isn't working with multiple joins.
The query:
var q = Db.From<Blog>(Db.TableAlias("b"))
.LeftJoin<Blog, BlogToBlogCategory>((b,btb)=> b.Id == btb.BlogId, Db.TableAlias("btbc"))
.Join<BlogToBlogCategory, BlogCategory>((bt,bc)=>bt.BlogCategoryId == bc.Id, Db.TableAlias("cats"))
.GroupBy(x => x.Id);
.Select("b.*, json_agg(cats) as BlogCategoriesJson");
var results = Db.Select<BlogQueryResponse>(q);
Generates this SQL:
SELECT b.*, json_agg(cats) as BlogCategoriesJson
FROM "blog" "b" LEFT JOIN "blog_to_blog_category" "btbc" ON ("b"."id" = "btbc"."blog_id") INNER JOIN "blog_category" "cats" ON ("blog_to_blog_category"."blog_category_id" = "cats"."id")
GROUP BY "b"."id"
This causes error because it is referencing "blog_to_blog_category" instead of btbc
The Db.TableAlias() only provides an alias for the target join table, your inner join does not specify the alias to use for the source table so it references the full table name as expected.
You can use Sql.TableAlias() in your LINQ Expression to reference a table alias, e.g:
var q = Db.From<Blog>(Db.TableAlias("b"))
.LeftJoin<Blog, BlogToBlogCategory>((b,btb)=> b.Id == btb.BlogId, Db.TableAlias("btbc"))
.Join<BlogToBlogCategory, BlogCategory>((bt,bc)=>
Sql.TableAlias(bt.BlogCategoryId, "btbc") == bc.Id, Db.TableAlias("cats"))
.GroupBy(x => x.Id);
.Select("b.*, json_agg(cats) as BlogCategoriesJson");

How can I add primary key and foreign key constraints after export data from Azure SQL

I'm using SQL Server Management Studio 19 to migrate data from source database to target database.
I select SQL Server Native Client 11.0 as the Data Source.
For Destination I also use "SQL Server Native Client 11.0" and choose target database as destination.
The data was exported successfully but primary key and foreign key constraints aren't there. What do I missed?
Any help or any suggestions are appreciated. Thank you so much!
There are two ways to export the PK and FK.
Using SSMS to generate the sql script. We just need to select the tables. It will generate a script.sql in your local PC.
We also can write some scripts to export the PK and FK of the User tables manually.
I've created a sql script to export PK and FK from system tables and views.
2.1 We can use the following script to export PK.
select case when colNo = 1 then concat('alter table ',concat(concat(res.schemaName,'.'),res.tableName)) else '' end headerOne,
case when colNo = 1 then concat(concat('add constraint ' , res.PKName),' primary key( ') else '' end headerTwo,
case when colNo = 1 then colName else concat(',',colName) end headerThree,
case when colNo = s2.maxRow then ');' else '' end as headerFour
from (
select s.name as schemaName,i.name as PKName,ov.name as tableName,c.name as colName,k.colid as colNo,k.keyno as indexNO
from
sysindexes i
join sysindexkeys k on i.id = k.id and i.indid = k.indid
join sysobjects o on i.id = o.id
join sys.objects ov on o.id = ov.object_id
join sys.schemas s ON ov.schema_id = s.schema_id
join syscolumns c on i.id=c.id and k.colid = c.colid
where o.xtype = 'U' and exists(select 1 from sysobjects where xtype = 'PK' and name = i.name)
) res
left join
(select schemaName,PKName,tableName,max(rono) as maxRow
from
(
select s.name as schemaName,i.name as PKName,ov.name as tableName,c.name as colName, ROW_NUMBER() OVER (PARTITION BY s.name,i.name,ov.name ORDER BY o.name,k.colid) AS rono
from
sysindexes i
join sysindexkeys k on i.id = k.id and i.indid = k.indid
join sysobjects o on i.id = o.id
join sys.objects ov on o.id = ov.object_id
join sys.schemas s ON ov.schema_id = s.schema_id
join syscolumns c on i.id=c.id and k.colid = c.colid
where o.xtype = 'U' and exists(select 1 from sysobjects where xtype = 'PK' and name = i.name)
) s1
group by schemaName,PKName,tableName
) s2 on res.schemaName = s2.schemaName and res.PKName=s2.PKName and res.tableName=s2.tableName
2.2 Then we can copy the script from SSMS.
2.3 Then we paste the script to query window of the Staging database to execute the script.
2.4 After created PK, in the same way, we can export FK and create them.
select
concat(concat('alter table ',c.CONSTRAINT_SCHEMA),concat('.',fk.TABLE_NAME)),
concat(' add constraint ', c.CONSTRAINT_NAME), --cu.COLUMN_NAME
concat(' foreign key( ',cu.COLUMN_NAME),
concat(concat(') references ',c.CONSTRAINT_SCHEMA),concat('.',pk.TABLE_NAME)),
concat(concat('(',pt.COLUMN_NAME),');')
from
INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS c
inner join INFORMATION_SCHEMA.TABLE_CONSTRAINTS fk
on c.CONSTRAINT_NAME = FK.CONSTRAINT_NAME
inner join INFORMATION_SCHEMA.TABLE_CONSTRAINTS pk
on c.UNIQUE_CONSTRAINT_NAME = PK.CONSTRAINT_NAME
inner join INFORMATION_SCHEMA.KEY_COLUMN_USAGE cu
on c.CONSTRAINT_NAME = CU.CONSTRAINT_NAME
inner join (
select
i1.TABLE_NAME,
i2.COLUMN_NAME
from
INFORMATION_SCHEMA.TABLE_CONSTRAINTS i1
inner join INFORMATION_SCHEMA.KEY_COLUMN_USAGE i2
on i1.CONSTRAINT_NAME = i2.CONSTRAINT_NAME
where
i1.CONSTRAINT_TYPE = 'PRIMARY KEY'
) PT
on pt.TABLE_NAME = pk.TABLE_NAME

What is the alternative of EXISTS in cassandra?

I am trying to rewrite a SQLite query in CQL.
I know that there is no EXISTS keyword in CQL. I googled it's alternative. However, I couldn't find anything.
UPDATE users SET passsword = ? WHERE user_name = ? AND EXISTS(SELECT 1 FROM
users WHERE user_name = ? AND active_status = 1)
How can I write this query in CQL? Any help is appreciated. Thank you.
This query may be broken down to 2 queries and put an additional java logic to filter the subqueries.That will be 2 calls to database layer
Resultset rs = stmt.execute ("SELECT user_name FROM
users WHERE active_status = 1");
while ( rs.next()){
stmt.executeUpdate("UPDATE users SET passsword = ? WHERE user_name = "+rs.next());
}

How to pass main query column value to nested sub query Where condition?

I am writing this query with nested subquery to find PREPARED_BY, VERIFIED_BY, AUTHORIZED_BY depending on CONDATE from Expenditure table, but in my sub query the Expenditure table object CONDATE is not recognized and throws this error :
ORA-00904: "EX"."CONDATE": invalid identifier.
Code:
SELECT ex.conno,
ex.itemno,
ex.adv_no || ' ' || to_char(ex.condate, 'DD-MON-YYYY') chequenodate,
ex.conname,
ex.apaid,
ex.dpayment,
gf.gf_name,
expenditure_type,
ex.off_code,
ofc.officename,
ex.remarks,
(SELECT prepared_by
FROM (SELECT prepared_by
FROM authorization
WHERE (pre_last_date >= ex.condate OR pre_last_date IS NULL)
AND project_id = 128
ORDER BY id ASC)
WHERE rownum = 1) AS prepared_by,
(SELECT verified_by
FROM (SELECT verified_by
FROM authorization
WHERE (ve_last_date >= ex.condate OR ve_last_date IS NULL)
AND project_id = 128
ORDER BY id ASC)
WHERE rownum = 1) AS verified_by,
(SELECT authorized_by
FROM (SELECT authorized_by
FROM authorization
WHERE (au_last_date >= ex.condate OR au_last_date IS NULL)
AND project_id = 128
ORDER BY id ASC)
WHERE rownum = 1) AS authorized_by
FROM expenditure ex
INNER JOIN officecode ofc
ON ofc.off_code = ex.off_code
INNER JOIN coa_category ca
ON ca.coa_cat_id = ex.coa_cat_id
INNER JOIN g_fund_type gf
ON gf.gf_type_id = ca.gf_type_id
WHERE ex.conno = 'MGSP/PMU/NON/145'
AND ex.itemno = 149;
The problem you're experiencing is that parent table can only be referenced by a subquery one level down. You're trying to access columns from the parent table in the subquery two levels down, hence why you're getting the error.
In order to access the parent column in your subquery, you're going to need to rewrite it so that it's only one level down.
This can be achieved by using the KEEP FIRST/LAST aggregate function, e.g.:
SELECT ex.conno,
ex.itemno,
ex.adv_no || ' ' || to_char(ex.condate, 'DD-MON-YYYY') chequenodate,
ex.conname,
ex.apaid,
ex.dpayment,
gf.gf_name,
expenditure_type,
ex.off_code,
ofc.officename,
ex.remarks,
(SELECT MAX(a.prepared_by) KEEP (dense_rank FIRST ORDER BY a.id ASC)
FROM authorizatiion a
WHERE (a.pre_last_date >= ex.condate OR a.pre_last_date IS NULL)
AND a.project_id = 128) prepared_by,
(SELECT MAX(a.verified_by) KEEP (dense_rank FIRST ORDER BY a.id ASC)
FROM authorizatiion a
WHERE (a.ve_last_date >= ex.condate OR a.ve_last_date IS NULL)
AND a.project_id = 128) verified_by,
(SELECT MAX(a.authorized_by) KEEP (dense_rank FIRST ORDER BY a.id ASC)
FROM authorizatiion a
WHERE (a.au_last_date >= ex.condate OR a.au_last_date IS NULL)
AND a.project_id = 128) authorized_by
FROM expenditure ex
INNER JOIN officecode ofc ON ofc.off_code = ex.off_code
INNER JOIN coa_category ca ON ca.coa_cat_id = ex.coa_cat_id
INNER JOIN g_fund_type gf ON gf.gf_type_id = ca.gf_type_id
WHERE ex.conno = 'MGSP/PMU/NON/145'
AND ex.itemno = 149;
N.B. I have used MAX and FIRST here; this means that if there are multiple rows with the same lowest id, the highest value of the prepared_by column will be used. You could change this to MIN if you wanted the lowest value. This is only relevant if you have more than one row per id, otherwise it simply returns the value of the prepared_by column for the lowest id.

Converting a LEFT OUTER JOIN to Entity Framework

Here is a SQL Query I want to convert to EF4.3
command = database.GetSqlStringCommand(#"
select
H.AUTHENTICATION_ID,
USERNAME,
PERMISSIONS,
ORGANIZATION_IDENTIFIER,
O.ORGANIZATION_ID
from
AUTHENTICATION H
left join [AUTHORIZATION] T on H.AUTHENTICATION_ID=T.AUTHENTICATION_ID
join ORGANIZATION O on O.ORGANIZATION_ID = T.ORGANIZATION_ID
order by H.AUTHENTICATION_ID");
Here is the best LINQ I could come up with:
var query = from h in context.Authentications
join t in context.Authorizations on h.AuthenticationId equals t.Authentications.AuthenticationId
join o in context.Organizations on t.Organizations.OrganizationId equals o.OrganizationId
orderby
h.AuthenticationId
select new
{ AUTHENTICATION_ID = (Int16?)h.AuthenticationId,
h.Username,
t.Permissions,
o.OrganizationIdentifier,
OrganizationID = (Int16?)o.OrganizationId
};
I know i need to merge my first join (between Authorizations & Authentications) into, lets say x and apply DefaultIfEmpty but can't make out the syntax.
EDIT: Image for clarification:
Any help will be highly appreciated. Regards.
The basic syntax for a "left join" in Linq is like this:
from x in table1
join y in table2 on x.id equals y.id into jointable
from z in jointable.DefaultIfEmpty()
select new
{
x.Field1,
x.Field2,
x.Field3,
Field4 = z == null ? 0 : z.Field4
};
In your case, I'm a little confused because the entity relations you seem to be using in your Linq don't match the ones implied by your SQL; are the relationships here zero-or-one, zero-or-many, one-to-one, etc? Specifically, you're doing this:
from h in context.Authentications
join t in context.Authorizations on h.AuthenticationId equals t.Authentications.AuthenticationId
but your SQL implies that "Authentication" is the parent here with zero-or-more "Authorization" children, not the other way around, which would be more like:
from h in context.Authentications
from t in h.Authorizations.DefaultIfEmpty()
If you can give us a better idea of the data model and what data you expect to get out of it we can more easily explain how that query would look in Linq. Assuming that your relationships match what is implied by the SQL, you should be able to get what you want using the following Linq queries:
var query = from h in context.Authentications
from t in h.Authorizations.DefaultIfEmpty()
select new
{
h.AuthenticationId,
h.Username,
Permissions = t == null ? null : t.Permissions,
Organizations = t == null ? new EntitySet<Organization>() : t.Organizations
};
var query2 = from x in query
from o in x.organizations.DefaultIfEmpty()
select new
{
AUTHENTICATION_ID = (short?)x.AuthenticationId,
x.Username,
x.Permissions,
OrganizationIdentifier = o == null ? null : o.OrganizationIdentifier,
OrganizationID = o == null ? (short?)null : o.OrganizationID
};
Given the foreign keys that exist in the question diagram, how about something like this?
var query = from a in context.Authentications
select new
{
a.AuthenticationID,
a.Username,
a.Authorisations.Permissions ?? false,
a.Authorisations.Organisations.OrganisationIdentifier ?? 0
a.Authorisations.Organisations.OrganisationID ?? 0
};
I went ahead and moved the entire query to a Stored Procedure on the database. This solves the problem by avoiding LINQ and ObjectBuilder in the first place.

Resources