How to pass a parameter in defrule function? CLIPS - artificial-intelligence

I am new of CLIPS, thanks for your help.
THE ISSUE:
If I have below template:
(deftemplate user
(slot id (type INTEGER))
(slot firstname (type STRING))
(slot lastname (type STRING))
(slot username (type STRING))
(slot average (type FLOAT))
)
I would take the username value from facts and checking if there are two facts with same username but different average. For example, if We have:
(assert user (id 1) (firstname 'Mike') (lastname 'Mikeson') (username 'mike') (average 70.00))
(assert user (id 1) (firstname 'Mike') (lastname 'Mikeson') (username 'mike') (average 10.00))
(assert user (id 2) (firstname 'John') (lastname 'Johnson') (username 'john') (average 90.00))
I would count the facts with same username, so 'mike', and checking if first fact has same value in second fact in the average field.
I tried searching on internet but there are few information about CLIPS

CLIPS (6.4 2/9/21)
CLIPS>
(deftemplate user
(slot id (type INTEGER))
(slot firstname (type STRING))
(slot lastname (type STRING))
(slot username (type STRING))
(slot average (type FLOAT)))
CLIPS>
(deffacts users
(user (id 1) (firstname "Mike") (lastname "Mikeson") (username "mike") (average 70.00))
(user (id 1) (firstname "Mike") (lastname "Mikeson") (username "mike") (average 10.00))
(user (id 2) (firstname "John") (lastname "Johnson") (username "john") (average 90.00)))
CLIPS>
(defrule different-averages
(user (username ?un) (average ?avg1))
(user (username ?un) (average ?avg2&:(> ?avg2 ?avg1)))
=>
(println "User " ?un " has averages " ?avg1 " and " ?avg2 "."))
CLIPS> (reset)
CLIPS> (run)
User mike has averages 10.0 and 70.0.
CLIPS>

Related

How to cast nulls to blank and those with number to decimal 3 places?

If I want the output to be blank if there is no gpa, and rounded to 3 decimal places if there is a gpa - how do I get that in one statement?
Here are the 2 statements I have come up with that I am having trouble combining as one (for blank if answer is null and 3 places decimal if there is a gpa).
decimal 3 places:
NULLIF(cast(round(termgpa.gpa, 3) AS DECIMAL(18, 3)), 0)
if null then blank:
isnull(cast(termgpa.gpa as varchar), ' ')
How about using a case statement. Also, if you want the column to contain both blanks and decimal numbers you will have to cast it as a varchar. The below statement shows both null and non null.
declare #gpa decimal(18,5)
set #gpa = '5.789456'
select
case
when #gpa is null then ''
else cast(cast(round(#gpa, 3) AS DECIMAL(18, 3)) as varchar)
end as gpa
--returns 5.789
set #gpa = null
select
case
when #gpa is null then ''
else cast(cast(round(#gpa, 3) AS DECIMAL(18, 3)) as varchar)
end as gpa
--returns blank
CREATE TABLE [dbo].[termgpa](
[id] [int] NULL,
[gpa] [decimal](18, 3) NULL
) ON [PRIMARY]
GO
INSERT [dbo].[termgpa] ([id], [gpa]) VALUES (1, CAST(20.000 AS Decimal(18, 3)))
GO
INSERT [dbo].[termgpa] ([id], [gpa]) VALUES (2, NULL)
GO
INSERT [dbo].[termgpa] ([id], [gpa]) VALUES (3, CAST(15.761 AS Decimal(18, 3)))
GO
INSERT [dbo].[termgpa] ([id], [gpa]) VALUES (4, CAST(45.650 AS Decimal(18, 3)))
GO
INSERT [dbo].[termgpa] ([id], [gpa]) VALUES (5, NULL)
GO
INSERT [dbo].[termgpa] ([id], [gpa]) VALUES (6, CAST(78.100 AS Decimal(18, 3)))
GO
I have created sample table with just two columns. now you can either choose to covert your decimal column to varchar or you can set 0 instead of null value as follows
SELECT ISNULL(CAST(gpa AS VARCHAR(20)),'') FROM dbo.termgpa
or you can set 0 or -1 whenever gpa is null and handle the same in code
SELECT CASE WHEN gpa IS NULL THEN '0' ELSE CAST(gpa AS DECIMAL(18,3)) END FROM dbo.termgpa

SQLITE3 programming learning in Python

I've created a new sql base in pycharm and it gave me the next error message:
Traceback (most recent call last):
File "C:\Users\rnicolescu\Desktop\my_program.py", line 619 (line from the pycharm), in
cursor.execute("""INSERT INTO Names (id, firstname, surname, phonenumber)
sqlite3.OperationalError: table Names has no column named surname
and the code writen is as follows:
import sqlite3
with sqlite3.connect("Phonebook.db") as db:
cursor = db.cursor()
cursor.execute("""CREATE TABLE IF NOT EXISTS Names (
id integer PRIMARY KEY,
firstname text,
surname text,
phonenumber text);""")
cursor.execute("""INSERT INTO Names (id, firstname, surname, phonenumber)
VALUES ('1', 'Simon', 'Robert', '0725383561')""")
db.commit()
cursor.execute("""INSERT INTO Names (id, firstname, surname, phonenumber)
VALUES ('2', 'Robert', 'Mihai', '0725333698')""")
db.commit()
cursor.execute("""INSERT INTO Names (id, firstname, surname, phonenumber)
VALUES ('3', 'Marc', 'Aurelius', '0122238569')""")
db.commit()
cursor.execute("""INSERT INTO Names (id, firstname, surname, phonenumber)
VALUES ('4', 'Iulian', 'Constantin', '3532644226')""")
db.commit()
db.close()
Where should I look for the error? I can't figure it out. Thanks

How to show specific 2 rows at the top without order and then sort the rest by order using SQL DISTINCT, UNION

I have a country table with Id, Name with duplicate records. I am Using DISTINCT and UNION to show particular 2 country names Ireland and England at the top and rest all after By order name like below in SQL server
create table country (id int , name varchar(50));
insert into country (id, name) values( 1, 'Kuwait');
insert into country (id, name) values( 2, 'Australia');
insert into country (id, name) values( 3, 'Canada');
insert into country (id, name) values( 4, 'spain');
insert into country (id, name) values( 5, 'Turkey');
insert into country (id, name) values( 6, 'Ireland');
insert into country (id, name) values( 7, 'England');
insert into country (id, name) values( 1, 'Kuwait');
insert into country (id, name) values( 2, 'Australia');
insert into country (id, name) values( 3, 'Canada');
insert into country (id, name) values( 4, 'spain');
insert into country (id, name) values( 5, 'Turkey');
insert into country (id, name) values( 6, 'Ireland');
insert into country (id, name) values( 7, 'England');
DESIRED OUTPUT:
id name
-----------
6 Ireland
7 England
2 Australia
3 Canada
1 Kuwait
4 Spain
5 Turkey
Tried with DISTINCT & UNION in SQL QUERY:but names are not ordered after 3 row
select distinct id,name from country where id in (6,7)
union
select distinct id,name from country where id not in (6,7)
id name
-----------
6 Ireland
7 England
1 Kuwait
2 Australia
3 Canada
4 Spain
5 Turkey `
also tried with ORDER BY CASE:
select distinct id,name from country where id in (6,7)
union
select distinct id,name from country where id not in (6,7)
ORDER BY CASE
WHEN id = 6 and id = 7 -- whatever identifies that row
THEN 1 ELSE 2 END
ERROR:ORDER BY items must appear in the select list if the statement contains a UNION, INTERSECT or EXCEPT operator.
There is absolutely no guaranteed order of the returned result, unless order by is specified. Even if you find a query, that returned the rows in the desired order, on next run, tomorrow, or at client's site, it will not return them in the same order. So you must add an order by clause. You need to sort on some artificial values, like this:
declare #country table(id int , name varchar(50));
insert into #country (id, name) values( 1, 'Kuwait');
insert into #country (id, name) values( 2, 'Australia');
insert into #country (id, name) values( 3, 'Canada');
insert into #country (id, name) values( 4, 'spain');
insert into #country (id, name) values( 5, 'Turkey');
insert into #country (id, name) values( 6, 'Ireland');
insert into #country (id, name) values( 7, 'England');
insert into #country (id, name) values( 1, 'Kuwait');
insert into #country (id, name) values( 2, 'Australia');
insert into #country (id, name) values( 3, 'Canada');
insert into #country (id, name) values( 4, 'spain');
insert into #country (id, name) values( 5, 'Turkey');
insert into #country (id, name) values( 6, 'Ireland');
insert into #country (id, name) values( 7, 'England');
select id, name from (
select distinct id, name
from #country) t
order by case name when 'Ireland' then 'aaaaaaaaaaaaaaaaaaaaaaaa1' when 'England' then 'aaaaaaaaaaaaaaaaaaaaaaaa2' else name end

How can I compare multiple rows with other rows from two different table and check if they are equal or not?

I have 2 table named OptionText and SubmittedAns The first table contains the QuestionId OptionId and IsRight. Here IsRight is used for either the options against the question is either right or wrong.Here a QuestionId have multiple OptionId even can have one too. The second table represent what is submitted by the user. They can either select one option or multiple option based on their assumption. Now I need to make automatic script which will justify either the submitted answers against right or wrong.
Note: If a question have more than one correct option then the user have to select all right option, if one is missing then the result will be false. However if he selects all right answers then the answer will be true.
I have tried through this script. It's just able to count the selected numbers but can't justify the answer is either right or wrong. So I need help.
I can assume that I need a WHILE loop to check each element particularly. But how? So I need help. Here is my code.
CREATE TABLE OptionText(
[OptionTextId] [bigint] IDENTITY(1,1) NOT NULL,
[QuestionId] [bigint] NOT NULL,
[IsRightAnswer] [bit] NOT NULL)
Insert into OptionText (QuestionId, IsRightAnswer) VALUES (5, 1)
Insert into OptionText (QuestionId, IsRightAnswer) VALUES (5, 0)
Insert into OptionText (QuestionId, IsRightAnswer) VALUES (5, 0)
Insert into OptionText (QuestionId, IsRightAnswer) VALUES (17, 0)
Insert into OptionText (QuestionId, IsRightAnswer) VALUES (17, 1)
Insert into OptionText (QuestionId, IsRightAnswer) VALUES (17, 1)
CREATE TABLE SubmittedAns(
[Id] [bigint] IDENTITY(1,1) NOT NULL,
[QuestionId] [bigint] NOT NULL,
[OptionTextId] [bigint] NOT NULL)
Insert into SubmittedAns (QuestionId, OptionTextId) VALUES (5, 1)
Insert into SubmittedAns (QuestionId, OptionTextId) VALUES (5, 2)
Insert into SubmittedAns (QuestionId, OptionTextId) VALUES (2, 1)
Insert into SubmittedAns (QuestionId, OptionTextId) VALUES (2, 1)
select * from OptionText
select * from SubmittedAns
if (select count(OptionTextId) from SubmittedAns where QuestionId =5) = (select count(ot.OptionTextId) from OptionText as ot where ot.IsRightAnswer = 1)
select 1 as "isRight"
else
select 0 as "isRight"
Please refer to first & last line for critical material:
SELECT CASE COUNT(*) WHEN 0 THEN 'Pass' ELSE 'Fail' END AS Boolean
FROM (
SELECT *
FROM #OptionText
WHERE QuestionId = 5
AND IsRightAnswer = 1
) AS OT
FULL OUTER JOIN #SubmittedAns AS SA ON OT.QuestionId = SA.QuestionId AND OT.OptionTextId = SA.OptionTextId
WHERE SA.QuestionId = 5
AND OT.OptionTextId IS NULL -- This means some answers failed to be matched with your original questions/options, either because IsRightAnswer is zero, or because it doesn't exist in your questions/answers.
I got a solution on my way of understanding. So I have used a function to apply it for all question and created this code. It's working.
CREATE FUNCTION [dbo].[Set_IsCorrect_Answer_Deva]
(
#QuestionId BIGINT
)
RETURNS BIT
AS
BEGIN
DECLARE #IsRightAns BIT
DECLARE #count int
set #IsRightAns = 0
Declare #supplied_count int
select #supplied_count = Count(*) from SuppliedAnswersTemp where QuestionId=#QuestionId
IF(#supplied_count>0)
Begin
IF(#supplied_count=(select Count(*) from OptionText where QuestionId=#QuestionId and IsRightAnswer=1))
Begin
select #count=Count(*) from OptionText ot join SuppliedAnswersTemp sa on ot.QuestionId = sa.QuestionId
where ot.QuestionId= #QuestionId and ot.IsRightAnswer =1 and ot.Id=sa.OptionId
END
END
IF(#count>0)
Set #IsRightAns=1
RETURN #IsRightAns
END

Handling duplicate values in update query with UQ column

I am migrating user information from few source databases and generating Usernames in destination to those users that are compiled in two ways: 1. If user does not belong to 'usergroup' username is lastname+runningnumber(for duplicates) 2. if they belong to usergroup their username is usergroup+runningnumber. RunningNumber should not be 'universal' across all users, but instead limited to duplicates f.ex
User1,User2,User3,UserGroup1,UserGroup2,UserGroup3
It was suggested to me that this will be simpler to achieve outside of SSIS.
When running the query duplicate values might exists already in dest.db or they might be generated via query.
This is my current query (not working properly) and I need some help in approaching this issue:
SET XACT_ABORT OFF ;
BEGIN
DECLARE #Any_error int;
WITH Kep as (SELECT Id, CASE WHEN UserGroup IS NULL THEN CAST(LEFT(LOWER(REPLACE(LastName, ' ','')), 10) +'-'+
RIGHT(CAST(ROW_NUMBER() OVER(PARTITION BY LEFT(LOWER(REPLACE(LastName, ' ','')), 10) ORDER BY LastName) as nvarchar(50)),4) AS nvarchar(50)) ELSE CAST(LEFT(LOWER(REPLACE(UserGroup, ' ','')), 10) +'-'+
RIGHT(+CAST(ROW_NUMBER() OVER(PARTITION BY LEFT(LOWER(REPLACE(UserGroup, ' ','')), 10) ORDER BY UserGroup) as nvarchar(50)),4) AS nvarchar(50)) END AS rn
FROM Users)
UPDATE TOP(1000) Users
SET UserName = rn
SELECT #Any_error = ##ERROR
IF #Any_error = 2627 GOTO ErrorHandler
ErrorHandler:
DECLARE #RunningNumber INT
SET #RunningNumber = 1
Loop:
BEGIN
WHILE (#Any_error = 2627)
SET #RunningNumber = #RunningNumber+1;
WITH Kep as (SELECT Id, CASE WHEN UserGroup IS NULL THEN CAST(LEFT(LOWER(REPLACE(LastName, ' ','')), 10) +'-'+
RIGHT(+CAST(ROW_NUMBER() OVER(PARTITION BY LEFT(LOWER(REPLACE(LastName, ' ','')), 10) ORDER BY LastName)+#RunningNumber as nvarchar(50)),4) AS nvarchar(50)) ELSE CAST(LEFT(LOWER(REPLACE(UserGroup, ' ','')), 10) +'-'+
RIGHT(+CAST(ROW_NUMBER() OVER(PARTITION BY LEFT(LOWER(REPLACE(UserGroup, ' ','')), 10) ORDER BY UserGroup)+#RunningNumber as nvarchar(50)),4) AS nvarchar(50)) END AS rn
FROM Users)
UPDATE Users
SET UserName = rn
SELECT #Any_error = ##ERROR
IF (#Any_error = 2627) GOTO Loop;
END
END
Any advice / help is highly appreciated!
EDIT: Data..
Source
LastName UserGroup
Smith Sales
Smith Sales
Smith NULL
Smith NULL
Johnson Development
Johnson NULL
Destination
LastName UserGroup Username
Smith Sales sales-1
Smith Sales sales-2
Smith NULL smith-1
Smith NULL smith-2
Johnson Development development-1
Johnson NULL johnson-1
Yikes, your query looks scary. Try something like this:
My Versions of Your Tables
DECLARE #yourTable TABLE (LastName VARCHAR(15),UserGroup VARCHAR(15));
INSERT INTO #yourTable
VALUES ('Smith','Sales'),
('Smith','Sales'),
('Brown','Sales'), --added this row
('Smith',NULL),
('Smith',NULL),
('Johnson','Development'),
('Johnson',NULL);
DECLARE #destinationTable TABLE (LastName VARCHAR(15),UserGroup VARCHAR(15),UserName VARCHAR(15))
INSERT INTO #destinationTable
VALUES ('Smith',NULL,'Smith-1'),
('Stevens','Sales','Sales-1'),
('Stevens','Sales','Sales-2'),
('Lopez','Development','Development-1');
Actual Query
--INSERT INTO #destinationTable
SELECT LastName,
UserGroup,
COALESCE(UserGroup,LastName)
+ '-'
+ CAST(ROW_NUMBER() OVER (PARTITION BY COALESCE(UserGroup,LastName) ORDER BY (SELECT NULL)) + COALESCE(max_num,0) AS VARCHAR(10))
AS UserName
FROM #yourTable AS A
CROSS APPLY (
SELECT MAX(CAST(SUBSTRING(UserName,CHARINDEX('-',UserName) + 1,1000) AS INT)) --finds maximum number already used in destination table
FROM #destinationTable AS B
WHERE COALESCE(A.UserGroup,A.LastName) = COALESCE(B.UserGroup,B.LastName)
) CA(max_num)
Results:
LastName UserGroup UserName
--------------- --------------- --------------------------
Johnson Development Development-2
Johnson NULL Johnson-1
Smith Sales Sales-3
Smith Sales Sales-4
Brown Sales Sales-5
Smith NULL Smith-2
Smith NULL Smith-3
If you have a LastName same as a UserGroup this could produce duplicates
SELECT LastName,
UserGroup,
LEFT(LOWER(REPLACE(UserGroup, ' ','')), 10)
+ '-'
+ CAST(ROW_NUMBER() OVER (PARTITION BY LEFT(LOWER(REPLACE(UserGroup, ' ','')), 10) ORDER BY (SELECT NULL)) AS VARCHAR(10))
AS UserName
FROM Users
WHERE UserGroup is not null
SELECT LastName,
UserGroup,
LEFT(LOWER(REPLACE(LastName, ' ','')), 10)
+ '-'
+ CAST(ROW_NUMBER() OVER (PARTITION BY LEFT(LOWER(REPLACE(LastName, ' ','')), 10) ORDER BY (SELECT NULL)) AS VARCHAR(10))
AS UserName
FROM Users
WHERE UserGroup is null

Resources