Complex SQL syntax - django

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;

Related

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)

Understanding Secondary Indexes

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

Having trouble summing columns in SQL Server joined view

Moi guys, Matt here. I'm having trouble with a relatively complicated view. I have a parts and service table that each have unique identifiers for a given part/service. I'm trying to link these to a service invoice table and subsequent view as a M:N relationship, so I've set up intermediary relational tables, with both the invoice number (invoice primary key) and part/service number (part/service primary key) as the combined primary key. Here's my code for the whole relationship and view:
CREATE TABLE service_invoice
( servinv_Num VARCHAR2(10) CONSTRAINT serv_snum_PK PRIMARY KEY,
servinv_EmpID NUMBER(6) CONSTRAINT serv_empnum_FK REFERENCES employee(empID),
servinv_CustID NUMBER(6) CONSTRAINT serv_custid_FK REFERENCES customer(custID),
servinv_VIN VARCHAR2(25) CONSTRAINT serv_VIN_FK REFERENCES vehicle(vehicle_vin),
servinv_Terms VARCHAR2(6) CONSTRAINT serv_trms_NN NOT NULL,
servinv_Date DATE );
CREATE TABLE Parts
( PartID VARCHAR2(10) CONSTRAINT Part_PartID_PK PRIMARY KEY,
PartDesc VARCHAR2(50) CONSTRAINT Part_PartDesc_NN NOT NULL,
PartCharge NUMBER(4,2) CONSTRAINT Part_PartCharge_NN NOT NULL );
CREATE TABLE Service
( ServiceID VARCHAR2(10) CONSTRAINT Serv_ServID_PK PRIMARY KEY,
ServDesc VARCHAR2(50) CONSTRAINT Serv_ServName_NN NOT NULL,
ServCharge NUMBER(4,2) CONSTRAINT Serv_ServCharge_NN NOT NULL );
CREATE TABLE Serv_SI_Rel
( SI_num VARCHAR2(10) CONSTRAINT ServSI_SInum_FK REFERENCES service_invoice(servinv_Num),
ServiceID VARCHAR2(10) CONSTRAINT ServSI_ServID_FK REFERENCES Service(ServiceID),
CONSTRAINT ServSI_SInum_ServID_PK PRIMARY KEY(SI_num, ServiceID) );
CREATE TABLE Parts_SI_Rel
( SI_num VARCHAR2(10) CONSTRAINT PartSI_SInum_FK REFERENCES service_invoice(servinv_Num),
PartID VARCHAR2(10) CONSTRAINT PartSI_PartID_FK REFERENCES Parts(PartID),
CONSTRAINT PartSI_SInum_PartID_PK PRIMARY KEY(SI_num, PartID) );
CREATE OR REPLACE VIEW ServiceInvoiceDoc
AS
(
SELECT si.servinv_Num, si.servinv_Date, si.servinv_Terms,
es.empName,
sc.custName, sc.custHouse, sc.custCity,
sc.custState, sc.custZIP, sc.custPhone, sc.custEmail,
sv.vehicle_VIN, sv.vehicle_mileage,
srel.ServiceID,
prel.PartID,
s.ServDesc, s.ServCharge,
p.PartDesc, p.PartCharge,
SUM(s.ServCharge) TotalServCharges,
SUM(p.PartCharge) TotalPartsCharges,
( SUM(s.ServCharge)+SUM(p.PartCharge) ) SubTotalCharges,
( SUM(s.ServCharge)+SUM(p.PartCharge) )*0.0825 Taxes,
( SUM(s.ServCharge)+SUM(p.PartCharge) )*1.0825 TotalCharges
FROM service_invoice si
JOIN employee es
ON (es.empID = si.servinv_EmpID)
JOIN customer sc
ON (sc.custID = si.servinv_CustID)
JOIN vehicle sv
ON (sv.vehicle_VIN = si.servinv_VIN)
LEFT OUTER JOIN Serv_SI_Rel srel
ON (srel.SI_Num = si.servinv_Num)
LEFT OUTER JOIN Parts_SI_Rel prel
ON (prel.SI_num = si.servinv_Num)
JOIN Parts p
ON (prel.PartID = p.PartID)
JOIN Service s
ON (srel.ServiceID = s.ServiceID) );
The error I get has to do with summing the individual parts and service charges in the M:N relationship. Here's the error code from the run:
ORA-00937: not a single-group group function
I've tried fixing with a group by command, but the grouping identifier (service invoice) isn't included on the part or service tables, and the joins don't seem to link these up for a group. e.g. I tried calling GROUP BY si.servinv_Num
Can this be resolved at all or is it completely wrong? I have the option of dropping the M:N relationship as a 1:M and simply making a separate invoice for each part/service charge, but I would prefer to keep it compact and professional.
Any help would be greatly appreciated. Thank you so much for your time!
a) wrong tag
b) I'd imagine you would need to list all columns in group by clause that aren't aggregated, as per Oracle
...
group by si.servinv_Num, si.servinv_Date, si.servinv_Terms,
es.empName,
sc.custName, sc.custHouse, sc.custCity,
sc.custState, sc.custZIP, sc.custPhone, sc.custEmail,
sv.vehicle_VIN, sv.vehicle_mileage,
srel.ServiceID,
prel.PartID,
s.ServDesc, s.ServCharge,
p.PartDesc, p.PartCharge

How to insert values in the different table by adding values to only one table using sql query?

I have a table 'Person' with columns as 'Person_id as primary key','DOB' and 'place' as follows:
'Person'
Person_id |Name|DOB | place
Another table is "employee" where emp_id is primary key as follows:
'employee'
Person_id |emp_id|dateofjoin
And one more table "Details":
'Details'
emp_id|competency|rating
Now what i want is once i add the 'Person' table details the rest of the two tables as'employe' and 'Details' to get updated also with respect to the new Person added in the Person table. So, how can i have this using sql query? Also i want to clear that i am not very much familiar with database.
I think your after something like this ( for SQL Server ):
Create Procedure dbo.CreateMyEmployee ( #empName varchar(50),
#dob datetime,
#doj datetime,
#place as varchar(100),
#competency varchar(100),
#rating int)
As
Begin
Declare #empId int
Begin Transaction
Begin Try
Insert into Person (Name, DOB, Place)
Values ( #empName, #dob, #place)
Insert into employe (Name, dateofJoin) -- Assuming emp_id is identity columen
Values ( #empName, #doj)
Select #empId = SCOPE_IDENTITY()
Insert Into Details(emp_id, competency, rating)
Values (#empId, #competency, #rating)
Commit transaction
End Try
Begin Catch
Rollback Transaction
SELECT ERROR_NUMBER() AS ErrorNumber, ERROR_MESSAGE() AS ErrorMessage
End Catch
End

How to update and set unit_id to be NULL, unit id is foreign key from unit table

How to update and set unit_id to be NULL, unit id is foreign key and I need to set to be NULL
CREATE TABLE troops
(
id serial NOT NULL,
unit_id integer,
type integer NOT NULL,
level integer NOT NULL,
CONSTRAINT troops_pkey PRIMARY KEY (id),
CONSTRAINT troops_unit_id_fkey FOREIGN KEY (unit_id)
REFERENCES units (id) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE CASCADE
)
WITH (
OIDS=FALSE
);
I have tried to update troops and set unit_id to be NULL ( I put NULL not 0 in pqxx statement in C++ ) but I get error like
insert or update on table "troops" violates foreign key constraint "troops_unit_id_fkey"
DETAIL: Key (unit_id)=(0) is not present in table "units".
When I try from pgadmin I can set unit_id to be NULL in troops but pqxx ( from c++ code I try to update) converts NULL to 0, how to solve this ?