Insert trigger SQL: missing FROM-clause entry for table - sql

I'm using Postgres and I'm trying to create a trigger for insert or update new values into a table.
Here are the trigger and the function:
create or replace function trigf1() returns trigger as $$
begin
if (ballotbox.totvoters>votes.nofvotes) then
raise notice 'more voters than allowed';
return old;
else return new;
end if;
end;
$$ language plpgsql;
create trigger T1
Before insert or update on votes
for each row
execute procedure trigf1();
When I'm trying to update the tables "votes" and "ballotBox" I'm getting the error:
ERROR: missing FROM-clause entry for table "ballotbox"
LINE 1: SELECT (ballotbox.totvoters > votes.nofvotes)
^
QUERY: SELECT (ballotbox.totvoters > votes.nofvotes)
CONTEXT: PL/pgSQL function trigf1() line 3 at IF
I don't know if it's needed but here are the create tables and the insert values:
create table ballotBox
(bno integer,
cid numeric(4,0),
street varchar(20),
hno integer,
totvoters integer,
primary key (bno),
foreign key (cid) references city);
create table votes
(cid numeric(4,0),
bno integer,
pid numeric(3,0),
nofvotes integer,
foreign key (cid) references city,
foreign key (bno) references ballotBox,
foreign key (pid) references party,
check (nofvotes >= 0));
insert into ballotBox values
(1, 1, 'street1', 10, 1500),
(2, 1, 'street2', 15, 490),
(3, 1, 'street2', 15, 610),
(4, 1, 'street2', 15, 650),
(5, 2, 'street3', 10, 900),
(6, 2, 'street3', 55, 800),
(7, 2, 'street4', 67, 250),
(8, 2, 'street4', 67, 990),
(9, 2, 'street5', 5, 600),
(10, 3, 'street1', 72, 1000),
(11, 3, 'street6', 25, 610),
(12, 3, 'street6', 25, 600),
(13, 4, 'street2', 3, 550),
(14, 4, 'street7', 15, 500),
(15, 5, 'street8', 44, 1100),
(16, 5, 'street9', 7, 710),
(17, 5, 'street10', 13, 950);
insert into votes values
(1, 1, 200, 100),
(1, 1, 210, 220),
(1, 1, 220, 2),
(1, 1, 230, 400),
(1, 1, 240, 313),
(1, 1, 250, 99),
(2, 1, 200, 55),
(2, 1, 210, 150),
(2, 1, 220, 2),
(2, 1, 230, 16),
(2, 1, 240, 210);

try this
if ((select totvoters from ballotbox) > (selecct nofvotes from votes))

Related

How much unique data is there, put it all in a table

I would like to query in SQL how many unique values ​​there are and how many rows are there. In Python, I could do it like this. But how do I do this in SQL so that I get the result like at the bottom?
In Python I could do the following
d = {'sellerid': [1, 1, 1, 2, 2, 3, 3, 3], 'modelnumber': [85, 45, 85, 12 ,85, 74, 85, 12]
, 'modelgroup': [2, 3, 2, 1, 2, 3, 2, 1 ]}
df = pd.DataFrame(data=d)
display(df.head(10))
df['Dataframe']='df'
unique_sellerid = df['sellerid'].nunique()
print("unique_sellerid", unique_sellerid)
unique_modelnumber = df['modelnumber'].nunique()
print("unique_modelnumber", unique_modelnumber)
unique_modelgroup = df['modelgroup'].nunique()
print("unique_modelgroup", unique_modelgroup)
total_rows = df.shape[0]
print("total_rows", total_rows)
[OUT]
unique_sellerid 3
unique_modelnumber 4
unique_modelgroup 3
total_rows 8
I want a query like
Here is the dummy table
CREATE TABLE cars (
sellerid INT NOT NULL,
modelnumber INT NOT NULL,
modelgroup INT,
);
INSERT INTO cars
(sellerid , modelnumber, modelgroup )
VALUES
(1, 85, 2),
(1, 45, 3),
(1, 85, 2),
(2, 12, 1),
(2, 85, 2),
(3, 74, 3),
(3, 85, 2),
(3, 12, 1);
You could use the count(distinct column) aggregation function like :
select
count(distinct col1) as nunique_col1,
count(distinct col2) as nunique_col2,
count(1) as nb_rows
from database
Also in pandas, you can also apply the nunique() function on the dataset, rather than doing it on each column: df.nunique()

Why is my sql script returning "[null]" and "0" values even though my table is populated?

I have manually populated a table as follows:
INSERT INTO country VALUES
-- columns are countryid, name, continent, population, gdp, lifeexpectancy, founded
(1, 'Argentina', 36.3, 348.2, 70.75, 9/7/1816),
(2, 'Brazil', 183.3, 1004, 65.6, 9/7/1822),
(3, 'Canada', 30.1, 658, 77.08, 1/7/1867),
(4, 'England', 60.8, 1256, 75.15, NULL),
(5, 'France', 60, 1000, 75.15, 14/7/1789),
(6, 'Mexico', 107.5, 694.3, 69.36, 16/9/1821),
(7, 'USA', 270, 8003, 75.75, 4/7/1776),
(8, 'Cuba', 11.7, 16.9, 75.95, 24/2/1895),
(9, 'Guatemala', 20, 200, 60, 15/9/1821),
(10, 'Tanzania', 55.57, 47.43, 60.76, 9/12/1961),
(11, 'India', 1324, 2264, 68.35, NULL),
(12, 'South Africa', 55.91, 294.8, 57.44, 31/05/1910),
(13, 'Costa Rica', 4.86, 57.44, 79.59, 15/9/1821),
(14, 'Uganda', 41.49, 25.53, 59.18, NULL);
but when I query
SELECT lifeexpectancy FROM country;
The tables returns a combination of "0" and "[null]" values.
I've tried changing the data_type of lifeexpectancy. Neither text nor numeric data types return values that have been entered.
Any suggestions?
You are not inserting the continent. Presumably you want that, but it is not in your sample data.
You should be using standard date formats. In most databases, YYYY-MM-DD works. And you should list the columns. So:
INSERT INTO country (countryid, name, population, gdp, lifeexpectancy, founded)
VALUES (1, 'Argentina', 36.3, 348.2, 70.75, '1816-07-09'),
(2, 'Brazil', 183.3, 1004, 65.6, '1822-07-09'),
(3, 'Canada', 30.1, 658, 77.08, '1867-07-01'),
(4, 'England', 60.8, 1256, 75.15, NULL),
(5, 'France', 60, 1000, 75.15, '1789-07-14'),
(6, 'Mexico', 107.5, 694.3, 69.36, '1821-09-16'),
(7, 'USA', 270, 8003, 75.75, '1776-07-04'),
(8, 'Cuba', 11.7, 16.9, 75.95, '1895-02-24'),
(9, 'Guatemala', 20, 200, 60, '1821-09-15'),
(10, 'Tanzania', 55.57, 47.43, 60.76, '1961-12-09'),
(11, 'India', 1324, 2264, 68.35, NULL),
(12, 'South Africa', 55.91, 294.8, 57.44, '1910-05-31'),
(13, 'Costa Rica', 4.86, 57.44, 79.59, '1821-09-15'),
(14, 'Uganda', 41.49, 25.53, 59.18, NULL);
I believe you're supplying 6 values instead of 7 (may be because of Auto Increment), if that the case you need to specify the columns here.
Also pass date with single quotes surrounded:
INSERT INTO country (countryid, name, continent, population, gdp, lifeexpectancy, founded)
VALUES
(1, 'Argentina', 36.3, 348.2, 70.75, '9/7/1816'),
(2, 'Brazil', 183.3, 1004, 65.6, '9/7/1822'),
(3, 'Canada', 30.1, 658, 77.08, '1/7/1867'),
(4, 'England', 60.8, 1256, 75.15, NULL),
(5, 'France', 60, 1000, 75.15, '14/7/1789'),
(6, 'Mexico', 107.5, 694.3, 69.36, '16/9/1821'),
(7, 'USA', 270, 8003, 75.75, '4/7/1776'),
(8, 'Cuba', 11.7, 16.9, 75.95, '24/2/1895'),
(9, 'Guatemala', 20, 200, 60, '15/9/1821'),
(10, 'Tanzania', 55.57, 47.43, 60.76, '9/12/1961'),
(11, 'India', 1324, 2264, 68.35, NULL),
(12, 'South Africa', 55.91, 294.8, 57.44, '31/05/1910'),
(13, 'Costa Rica', 4.86, 57.44, 79.59, '15/9/1821'),
(14, 'Uganda', 41.49, 25.53, 59.18, NULL);

SQL Server Management: The INSERT statement conflicted with the FOREIGN KEY constraint

I'm using SQL Server Management to create a database (fot a work in the university), I'm trying to insert new values into a table but recieving error.
The two relevant tables I created are:
create table ballotBox
(
bno integer,
cid numeric(4,0) references city,
street varchar(20),
hno integer,
totvoters integer,
primary key (bno)
);
create table votes
(
cid numeric(4,0) references city,
bno integer references ballotBox,
pid numeric(3,0) references party,
nofvotes integer
);
I've entered first the values to ballotBox (as well as for the table 'city' and 'party'):
insert into ballotBox values
(1, 1, 'street1', 10, 1500),
(2, 1, 'street2', 15, 490),
(3, 1, 'street2', 15, 610),
(4, 1, 'street2', 15, 650),
(5, 2, 'street3', 10, 900),
(6, 2, 'street3', 55, 800),
(7, 2, 'street4', 67, 250),
(8, 2, 'street4', 67, 990),
(9, 2, 'street5', 5, 600),
(10, 3, 'street1', 72, 1000),
(11, 3, 'street6', 25, 610),
(12, 3, 'street6', 25, 600),
(13, 4, 'street2', 3, 550),
(14, 4, 'street7', 15, 500),
(15, 5, 'street8', 44, 1100),
(16, 5, 'street9', 7, 710),
(17, 5, 'street10', 13, 950);
And then I tried to enter values to votes:
insert into votes values
(1, 1, 200, 100),
(1, 11, 210, 220),
(1, 1, 220, 2),
(1, 1, 230, 400),
(1, 1, 240, 313),
(1, 1, 250, 99),
(2, 1, 200, 55),
(2, 10, 210, 150),
(2, 10, 220, 2),
(2, 1, 230, 16),
(2, 1, 240, 210),
(2, 9, 250, 54),
(3, 9, 200, 234),
(3, 9, 210, 123),
(3, 1, 220, 8),
(3, 1, 230, 87),
(3, 1, 240, 76),
(3, 1, 250, 6),
(4, 1, 200, 135),
(4, 1, 210, 246),
(4, 17, 220, 7),
(4, 1, 230, 18),
(4, 1, 240, 44),
(4, 1, 250, 66),
(1, 2, 200, 373),
(1, 2, 210, 12),
(1, 2, 220, 3),
(1, 2, 230, 74),
(1, 2, 240, 58),
(1, 2, 250, 272),
(2, 6, 200, 139),
(2, 6, 210, 2580),
(2, 2, 220, 6),
(2, 2, 230, 73),
(2, 2, 240, 7),
(2, 2, 250, 99),
(3, 2, 200, 15),
(3, 2, 210, 68),
(3, 2, 220, 12),
(3, 2, 230, 12),
(3, 2, 240, 15),
(3, 2, 250, 25),
(4, 2, 200, 7),
(4, 2, 210, 245),
(4, 2, 220, 8),
(1, 0, 0.0, 361),
(4, 2, 240, 67),
(4, 2, 250, 144),
(5, 2, 200, 123),
(5, 2, 210, 76),
(5, 2, 220, 15),
(5, 2, 230, 158),
(5, 2, 240, 76),
(5, 2, 250, 132),
(1, 3, 200, 152),
(1, 3, 210, 517),
(1, 3, 220, 0),
(1, 3, 230, 267),
(2, 3, 200, 87),
(2, 3, 210, 134),
(2, 3, 220, 4),
(2, 3, 230, 11),
(2, 3, 240, 256),
(2, 3, 250, 76),
(3, 3, 200, 105),
(3, 3, 210, 132),
(3, 3, 3220, 3),
(3, 3, 230, 24),
(3, 3, 240, 254),
(3, 3, 250, 12),
(1, 4, 200, 61),
(1, 4, 210, 54),
(1, 4, 220, 5),
(1, 4, 230, 19),
(1, 4, 240, 1),
(1, 4, 250, 47),
(2, 4, 200, 17),
(2, 4, 210, 23),
(2, 4, 220, 0),
(2, 4, 230, 64),
(2, 4, 240, 11),
(2, 4, 250, 149),
(1, 5, 0200, 187),
(1, 5, 210, 88),
(1, 5, 220, 1),
(1, 5, 230, 255),
(1, 5, 240, 12),
(1, 5, 250, 373),
(2, 2, 500, 245),
(2, 5, 210, 120),
(2, 5, 220, 9),
(2, 5, 230, 19),
(2, 5, 240, 234),
(2, 5, 250, 5),
(3, 5, 200, 107),
(3, 5, 210, 18),
(3, 5, 220, 11),
(3, 5, 230, 54),
(3, 5, 240, 378),
(3, 5, 250, 243);
But I'm getting an error:
Msg 547, Level 16, State 0, Line 1
The INSERT statement conflicted with the FOREIGN KEY constraint "FK__votes__bno__1920BF5C". The conflict occurred in database "Voting", table "dbo.ballotBox", column 'bno'. The statement has been terminated.
you are trying to insert
(1, 0, 0.0, 361),
in votes table have FK bno
there are no record corresponding to 0 in ballotbox table
please remove this line from votes statement then insert
The relationship between two tables is not correct.
Make it so:
create table votes
(
cid numeric(4,0),
bno integer,
pid numeric(3,0),
nofvotes integer
foreing key cid reference city(cid)
foreing key bno reference ballotbox (bno)
foreing key pid reference party(pid)
);

How to get previous value from a log

I have a situation where at some point in the past some records in a table were modified to have duplicated information.
Consider an example below:
create table #CustomerExample
(
CustomerRecordId int,
CustomerId int,
CustomerName varchar(255),
CurrentCustomerValue varchar(255)
);
create table #CustomerExampleLog
(
LogId int,
CustomerRecordId int,
CustomerId int,
LogCreateDate datetime,
NewCustomerValue varchar(255)
);
insert #CustomerExample
values
(1, 100, 'Customer 1', 'Value X'),
(2, 100, 'Customer 1', 'Value X'),
(3, 200, 'Customer 2', 'Value Z'),
(4, 200, 'Customer 2', 'Value Z'),
(5, 200, 'Customer 2', 'Value Z');
insert #CustomerExampleLog
values
(1, 1, 100, '1/1/2014', 'Value B'),
(2, 1, 100, '2/1/2014', 'Value C'),
(3, 1, 100, '3/1/2014', 'Value B'),
(4, 1, 100, '4/1/2014', 'Value X'),
(5, 1, 100, '5/1/2014', 'Value X'),
(6, 1, 100, '6/1/2014', 'Value X'),
(7, 2, 100, '1/1/2014', 'Value D'),
(8, 2, 100, '2/1/2014', 'Value E'),
(9, 2, 100, '3/1/2014', 'Value F'),
(10, 2, 100, '4/1/2014', 'Value G'),
(11, 2, 100, '5/1/2014', 'Value X'),
(12, 2, 100, '6/1/2014', 'Value X'),
(13, 3, 200, '1/2/2014', 'Value A'),
(14, 3, 200, '1/3/2014', 'Value A'),
(15, 3, 200, '1/4/2014', 'Value B'),
(16, 3, 200, '1/5/2014', 'Value Z'),
(17, 4, 200, '1/2/2014', 'Value A'),
(18, 4, 200, '1/3/2014', 'Value A'),
(19, 4, 200, '1/4/2014', 'Value Z');
Originally "Customer 1" and "Customer 2" had different values in CustomerValue column for each record in [#CustomerExample] table. However, due to lack of a proper unique constraint, a bunch of "bad" UPDATE statements resulted in duplicated info. The updates were logged to [#CustomerExampleLog] table, which contains only the ID of the updated record, the update date, and the new value. My goal is to re-trace the log entries and revert one of the duplicates to it's "last known good" value before it became a dupe.
Ideally, I want to revert the CurrentCustomerValue for one of the dupes to a previous value. In the above example it would be the LogId=3 for CustomerRecordId=1, and LogId=15 for CustomerRecordId=3.
I am completely stumped.
Do you want something like this?
SELECT *
, prev_value = (
SELECT TOP 1 NewCustomerValue
FROM #CustomerExampleLog l
WHERE c.CustomerRecordId = l.CustomerRecordId
AND l.NewCustomerValue <> c.CurrentCustomerValue
ORDER BY LogCreateDate DESC
)
FROM #CustomerExample c
If you are looking to do it selectively (one record at a time), this would update the value.
UPDATE Customerexample
SET Currentcustomervalue = a.Newcustomervalue
FROM Customerexamplelog a
WHERE Logid IN(SELECT MAX(Logid)
FROM Customerexamplelog L
INNER JOIN Customerexample C ON L.Customerrecordid = C.Customerrecordid
AND L.Newcustomervalue <> C.Currentcustomervalue
WHERE L.Customerrecordid = #custid);

How to select unique subsequences in SQL?

In generic terms I have a sequence of events, from which i'd like to select unique non-repeatable sequences using MS SQL Server 2008 R2.
Specifically in this case, each test has a series of recordings, each of which have a specific sequence of stimuli. I'd like to select the unique sequences of stimuli from inside the recordings of one test, insert them into another table and assign the sequence group id to the original table.
DECLARE #Sequence TABLE
([ID] INT
,[TestID] INT
,[StimulusID] INT
,[RecordingID] INT
,[PositionInRecording] INT
,[SequenceGroupID] INT
)
INSERT #Sequence
VALUES
(1, 1, 101, 1000, 1, NULL),
(2, 1, 102, 1000, 2, NULL),
(3, 1, 103, 1000, 3, NULL),
(4, 1, 103, 1001, 1, NULL),
(5, 1, 103, 1001, 2, NULL),
(6, 1, 101, 1001, 3, NULL),
(7, 1, 102, 1002, 1, NULL),
(8, 1, 103, 1002, 2, NULL),
(9, 1, 101, 1002, 3, NULL),
(10, 1, 102, 1003, 1, NULL),
(11, 1, 103, 1003, 2, NULL),
(12, 1, 101, 1003, 3, NULL),
(13, 2, 106, 1004, 1, NULL),
(14, 2, 107, 1004, 2, NULL),
(15, 2, 107, 1005, 1, NULL),
(16, 2, 106, 1005, 2, NULL)
After correctly identifying the unique sequences, the results should look like this
DECLARE #SequenceGroup TABLE
([ID] INT
,[TestID] INT
,[SequenceGroupName] NVARCHAR(50)
)
INSERT #SequenceGroup VALUES
(1, 1, '101-102-103'),
(2, 1, '103-103-101'),
(3, 1, '102-103-101'),
(4, 2, '106-107'),
(5, 2, '107-106')
DECLARE #OutcomeSequence TABLE
([ID] INT
,[TestID] INT
,[StimulusID] INT
,[RecordingID] INT
,[PositionInRecording] INT
,[SequenceGroupID] INT
)
INSERT #OutcomeSequence
VALUES
(1, 1, 101, 1000, 1, 1),
(2, 1, 102, 1000, 2, 1),
(3, 1, 103, 1000, 3, 1),
(4, 1, 103, 1001, 1, 2),
(5, 1, 103, 1001, 2, 2),
(6, 1, 101, 1001, 3, 2),
(7, 1, 102, 1002, 1, 3),
(8, 1, 103, 1002, 2, 3),
(9, 1, 101, 1002, 3, 3),
(10, 1, 102, 1003, 1, 3),
(11, 1, 103, 1003, 2, 3),
(12, 1, 101, 1003, 3, 3),
(13, 2, 106, 1004, 1, 4),
(14, 2, 107, 1004, 2, 4),
(15, 2, 107, 1005, 1, 5),
(16, 2, 106, 1005, 2, 5)
This is fairly easy to do in MySQL and other databases that support some version of GROUP_CONCAT functionality. It's apparently a good deal harder in SQL Server. Here's a stackoverflow question that discusses one technique. Here's another with some information about SQL Server 2008 specific solutions that might also get you started.
This will do it. Had to add an column to #SequenceGroup.
DECLARE #Sequence TABLE
([ID] INT
,[TestID] INT
,[StimulusID] INT
,[RecordingID] INT
,[PositionInRecording] INT
,[SequenceGroupID] INT
)
INSERT #Sequence
VALUES
(1, 1, 101, 1000, 1, NULL),
(2, 1, 102, 1000, 2, NULL),
(3, 1, 103, 1000, 3, NULL),
(4, 1, 103, 1001, 1, NULL),
(5, 1, 103, 1001, 2, NULL),
(6, 1, 101, 1001, 3, NULL),
(7, 1, 102, 1002, 1, NULL),
(8, 1, 103, 1002, 2, NULL),
(9, 1, 101, 1002, 3, NULL),
(10, 1, 102, 1003, 1, NULL),
(11, 1, 103, 1003, 2, NULL),
(12, 1, 101, 1003, 3, NULL),
(13, 2, 106, 1004, 1, NULL),
(14, 2, 107, 1004, 2, NULL),
(15, 2, 107, 1005, 1, NULL),
(16, 2, 106, 1005, 2, NULL)
DECLARE #SequenceGroup TABLE
([ID] INT IDENTITY(1, 1)
,[TestID] INT
,[SequenceGroupName] NVARCHAR(50)
,[RecordingID] INT
)
insert into #SequenceGroup
select TestID, (stuff((select '-' + cast([StimulusID] as nvarchar(100))
from #Sequence t1
where t2.RecordingID = t1.RecordingID
for xml path('')), 1, 1, '')), RecordingID
from #Sequence t2
group by RecordingID, TestID
order by RecordingID
select * from #SequenceGroup
update #Sequence
set SequenceGroupID = sg.ID
from #Sequence s
join #SequenceGroup sg on s.RecordingID=sg.RecordingID and s.TestID=sg.testid
select * from #Sequence