Understanding Secondary Indexes - google-cloud-platform

if i have Table
Table
CREATE TABLE Users (
userId STRING(36) NOT NULL,
contactName STRING(300) NOT NULL,
eMail STRING(100) NOT NULL,
....
) PRIMARY KEY (userId)
and secondary index
CREATE NULL_FILTERED INDEX ActiveUsersByEMail
ON Users (
eMail,
isActive,
)
and i select record by:
SELECT * FROM Users WHERE eMail = 'test#test.com' AND isActive = TRUE
spanner will automatically look at index, take userId and give me a record ?.
or i need to create
CREATE NULL_FILTERED INDEX ActiveUsersByEMail_01
ON Users (
eMail,
isActive,
userId
)
and first take userId by:
SELECT userId from Users#{FORCE_INDEX=ActiveUsersByEMail_01} WHERE eMail = 'test#test.com' AND isActive = TRUE
and then i take a record by:
`SELECT * FROM Users WHERE userId = '${userId}'``
Question is automatically use or not spanner secondary indices for standard select if condition match secondary index keys?

You should use FORCE_INDEX as Cloud Spanner will only choose an index in rare circumstances as stated here. You can use the STORING clause to add data directly to the index, allowing you to read the data directly from the index to avoid the second call. This is suggested for common query patterns in your application.

In github i ask same question and It turned out that this is easily done (without creating additional index) by:
SELECT * from Users#{FORCE_INDEX=ActiveUsersByEMail} WHERE eMail = 'test#test.com' AND isActive = TRUE
At this time the search is going on index and row come with all fields

Related

How to set session oracle apex?

SUPPOSE If i run any form in apex and then I will update any record then they get capture "APEX_PUBLIC_USER".
I want to capture my login user id by default using login URL
how to solve this ??
I'm not sure I understand what
I want to capture my login user id by default using login URL
means, but - user who is currently logged in is contained in :APP_USER so I suggest you use it.
The best practice in APEX to capture the audit fields (created_by, created, updated_by, update) is to use a trigger on the table. That way no coding is needed in apex itself.
Suppose you have a table rahul with a column "name" that you want to add records to via apex. Then you'd just create a form with the page item P1_NAME and let the database handle the other columns for you with the trigger.
create table rahul (
id number generated by default on null as identity
constraint koen_id_pk primary key,
name varchar2(255 char),
created date not null,
created_by varchar2(255 char) not null,
updated date not null,
updated_by varchar2(255 char) not null
)
;
-- triggers
create or replace trigger rahul_biu
before insert or update
on rahul
for each row
begin
if inserting then
:new.created := sysdate;
:new.created_by := coalesce(sys_context('APEX$SESSION','APP_USER'),user);
end if;
:new.updated := sysdate;
:new.updated_by := coalesce(sys_context('APEX$SESSION','APP_USER'),user);
end rahul_biu;
/

Oracle Apex IG force user to have filter on column

I need to force user to have filter on column with date. Dataset is rly big and it must-have. I know how to force user to have any filter. Just add to "Where":
:apex$f1 is not null
But I need to find how to force user to have filter on specific column
Like i wrote in comment this is solution (I couldn't find better one)
In 'Where Clause' I added this
EXISTS (SELECT /*+ NO_UNNEST */ F.*, R.*, C.* FROM apex_appl_page_ig_rpt_filters F, APEX_APPL_PAGE_IG_RPTS R, APEX_APPL_PAGE_IG_COLUMNS C
WHERE 1=1
AND F.report_id = R.report_id AND C.column_id = F.column_id
AND F.APPLICATION_ID = 100 AND F.PAGE_ID = 100
AND C.NAME = 'MY_COLUMN_NAME'
AND C.REGION_NAME = 'MY_REGION_NAME'
AND R.SESSION_ID = :APP_SESSION)
This checks setting of IG in apex objects. In addition you just need to wrote in Messages "When No Data Found" something about that column that is required, just to inform users.

How to search through rows and assign column value based on search in Postgres?

I'm creating an application similar to Twitter. In that I'm writing a query for the profile page. So when the user visits someone other users profile, he/she can view the tweets liked by that particular user. So for that my query is retrieving all such tweets liked by that user, along with total likes and comments on that tweet.
But an additional parameter I require is whether the current user has liked any of those tweets, and if yes, I want it to retrieve it as boolean True in my query so I can display it as liked in UI.
But I don't know how to achieve this part. Following is a sub-query from my main query
select l.tweet_id, count(*) as total_likes,
<insert here> as current_user_liked
from api_likes as l
INNER JOIN accounts_user ON l.liked_by_id = accounts_user.id
group by tweet_id
Is there an inbuilt function in postgres that can scan through the filtered rows and check whether current user id is present in liked_by_id. If so mark current_user_liked as True, else False.
You want to left outer join back into the api_likes table.
select l.tweet_id, count(*) as total_likes,
case
when lu.twee_id is null then false
else true
end as current_user_liked
from api_likes as l
INNER JOIN accounts_user ON l.liked_by_id = accounts_user.id
left join api_likes as lu on lu.tweet_id = l.tweet_id
and lu.liked_by_id = <current user id>
group by tweet_id
This will continue to bring in the rows you are seeing and will add a row for the lu alias on api_likes. If no such row exists matching the l.tweet_id and the current user's id, then the columns from the lu alias will be null.

google cloud spanner parents, children, grandparents, grandchildren

some background:
I am building a schema where one account creates a session which is basically a payment and when some other account decides to pay a transaction is generated and the money is transferred to the account that initiated the session.
I want to be able to perform all kinds of queries on these table and I want this to be as efficient as possible.
I came up with this schema:
CREATE TABLE account (
accountId STRING(MAX) NOT NULL,
balance FLOAT64 NOT NULL,
) PRIMARY KEY(accountId);
CREATE TABLE session (
accountId STRING(MAX) NOT NULL,
sessionId STRING(MAX) NOT NULL,
amount FLOAT64 NOT NULL,
) PRIMARY KEY(accountId, sessionId),
INTERLEAVE IN PARENT account ON DELETE CASCADE;
CREATE TABLE `transaction` (
transactionId STRING(MAX) NOT NULL,
sessionId STRING(MAX) NOT NULL,
accountId STRING(MAX) NOT NULL,
) PRIMARY KEY(sessionId, transactionId),
INTERLEAVE IN PARENT session ON DELETE CASCADE;
CREATE INDEX PayersAccountForSession ON `transaction`(accountId),
INTERLEAVE IN account
Suppose we have two accounts with id account1 and account2. account1 creates a session for 100€ with id session so we get a row (account1, session, 100) in the session table. and then account2 decides to pay the 100€ and a transaction with id transaction is created giving us a row (transaction, session, account2) in the transaction table.
Right now this doesn't work because in the transaction table I have no reference to the accountId key from the parent table but in my case this accountId is a different id then the one in the session table.
I could do this:
CREATE TABLE `transaction` (
transactionId STRING(MAX) NOT NULL,
sessionId STRING(MAX) NOT NULL,
accountId STRING(MAX) NOT NULL,
payersAccountId STRING(MAX) NOT NULL,
) PRIMARY KEY(sessionId, accountId, transactionId),
INTERLEAVE IN PARENT session ON DELETE CASCADE;
But now I haven't found any way to create an interleaved index for the payersAccountId to the account table because the name doesn't match any key column in that table. This seems kind of weird to me I think it should be possible to create interleaved indexes to columns with different names (maybe it is but I am missing something).
What I need is a way to resolve this in a way that keeps all account, sessions and transactions in the same split and to be able to query accounts of the payer and the receiver starting in the transaction table. Also I would like to know if there is any way to create multiple interleaved indexes in the same table but based on different columns like in the example for accountId and payerAccountId.
Thanks for taking your time :)
It's not possible to interleave tables if they don't match with the column name.
Adding the payersAccountId to the transaction table is a good idea, with this you could do a query matching the payersAccountId with the sessionId and the accountid like the following:
SELECT * from account WHERE accountId = (SELECT payersAccountId FROM transaction WHERE sessionId = 1)

Complex SQL syntax

I have a game, and in the database I'm saving the user actions by date & time.
CREATE TABLE user_actions
(
aId BIGSERIAL PRIMARY KEY NOT NULL,
userId BIGINT NOT NULL REFERENCES users(uId) DEFERRABLE INITIALLY DEFERRED,
aDate TIMESTAMP without time zone DEFAULT now(),
aType INTEGER NOT NULL DEFAULT 0
);
My users are identified with email
CREATE TABLE users(
uId BIGSERIAL PRIMARY KEY NOT NULL,
uName VARCHAR (50) NOT NULL,
uEmail VARCHAR (75) UNIQUE NULL
);
and each day new prizes are added each day has a different number of prizes
CREATE TABLE prizes(
pId BIGSERIAL PRIMARY KEY NOT NULL,
pDate TIMESTAMP without time zone DEFAULT now(),
pType INTEGER NULL
pSize INTEGER NULL
);
This query list the userId and his last action date, per user
select distinct userId, max(aDate) from user_actions GROUP BY userId order by userId;
I want to create a query that will count the number of prizes added since each user last action.
I'm running:
OS: Debian
DB: Postgresql
code: Django
I think I will use CTE though It has not been tested
WITH last_actions AS (
SELECT DISTINCT userId, MAX(aDate) as last_logged
FROM user_actions
GROUP BY userId ORDER BY userId)
SELECT a.userId, COUNT(b.pDate)
FROM last_actions a, prizes b
WHERE b.pDate >= a.last_logged
GROUP BY a.userId;